Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 10712
  • Last Modified:

PostMessage won't work in C#?? Does any one has any clue????

I am trying to develop an appication that uses serial port a lot.
I am trying to create a thread (say SerialReceiveThread) that
indefinitely waits for the incoming data at the serial port instead of
polling the Serial port for the data (Which I think is very inefficent).
When the data is available, it should inform the UI thread with the data received.

I am trying to do the communication from SerialReceiveThread to UI thread
by using POSTMESSAGE, POSTTHREADMESSAGE, or even tried SENDMESSAGE. Surprisingly,
I don't see any compilation errors but the applicaion as a whole won't work.

When I override the PreProcessMessage() or WndProc() function and set a breakpoint,
I don't see any messages coming to these functions though the other thread appears
to be posting the messages.

Any ideas would be appreciated.

Thanks

Srini
0
divyakolus
Asked:
divyakolus
  • 8
  • 8
1 Solution
 
arielliveCommented:
To send a message you have to declare the API PostMessage
      [DllImport("user32.dll", CharSet=CharSet.Auto)]
            public static extern IntPtr PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
And call it passing the window handle, the message and the parameters.
To catch the message, override the WndProc() in the form/control that you use to check the events and compare the message like this
protected override void WndProc(ref Message m)
{
      if (m.Msg == m_Msge)
...
0
 
divyakolusAuthor Commented:
Let me make things more clear by posting piece of code. Here is the code. Just to make life easier, in the pasted code below, there is only one thread created by Windows before it loads the program into RAM. Even this one does not work. Am I doing anything wrong here???

            private const int WM_USER = 0x0400;      // C:\PF\MVS.NET2003\VC7\PlatFormSDK\Include\WinUser.h
            private const int WM_NULL = 0x0000;
            private System.Windows.Forms.Timer timer1;
            private const int WM_CUSTOM_MSG = WM_USER + 1;

            [DllImport("user32.dll", SetLastError = true)]
            static extern long PostMessage(long hwnd, long wMsg, long wParam, long lParam);

            [DllImport("user32.dll", SetLastError = true)]
            static extern long SendMessage(long hwnd, long wMsg, long wParam, long lParam);
      
            [DllImport("user32.dll", SetLastError = true)]
            static extern long PostThreadMessage(uint uiThreadId, long wMsg, long wParam, long lParam);

            public override bool PreProcessMessage(ref Message msg)
            {
                  switch( msg.Msg )
                  {
                        case WM_CUSTOM_MSG:
                              MessageBox.Show("Received Message");
                              return true;
                  }
                  return base.PreProcessMessage (ref msg);
            }

            private void timer1_Tick(object sender, System.EventArgs e)
            {
//                  MessageBox.Show("Main Thread Id is: " + AppDomain.GetCurrentThreadId().ToString());
                  PostThreadMessage( (uint)AppDomain.GetCurrentThreadId(), WM_CUSTOM_MSG, 0, 0);
            }
0
 
eternal_21Commented:
Put this before you call Application.Run:

  System.Windows.Forms.Application.AddMessageFilter(new UserMessageFilter());

Add this class to your source code:

  public class UserMessageFilter: System.Windows.Forms.IMessageFilter
  {
    private const int WM_USER = 0x0400;

    public bool PreFilterMessage(ref Message m)
    {
      switch(m.Msg)
      {
        case WM_USER + 1:
        {
          // Process Custom Message 1
          // ...
          return true;
        }
        case WM_USER + 2:
        {
          // Process Custom Message 2
          // ...
          return true;
        }
        default:
        {
          return false;
        }
      }
    }
  }

And then you should find that PostThreadMessage works quite well!

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
eternal_21Commented:
Note that the WndProc method will only process the message that are delivered to it (you could get its handle using Form.Handle to send it messages).
0
 
divyakolusAuthor Commented:
Thank you eternal_21.
0
 
divyakolusAuthor Commented:
Hey eternal_21, I got to ask you one thing. Does it work between threads as well or do we have to do anything more to make it work!!

Thanks
0
 
eternal_21Commented:
It will work across threads and processes.
0
 
eternal_21Commented:
The only issue I know of, is that PostThreadMessage messages will be dropped (ignored) if there is a modal form displayed (e.g.: MessageBox.Show(), or Form.ShowDialog()).
0
 
divyakolusAuthor Commented:
I don't why but POSTMESSAGE function won't work even on the same thread. PostThreadMessage works. Do you know why??
0
 
eternal_21Commented:
Can you post your PostMessage code?
0
 
divyakolusAuthor Commented:
Here it is:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;

namespace WindowsApplication1
{
      public class UserMessageFilter: System.Windows.Forms.IMessageFilter
      {
            private const int WM_USER = 0x0400;

            public bool PreFilterMessage(ref Message m)
            {
                  switch(m.Msg)
                  {
                        case 0x0401:
                        {
                              // Process Custom Message 1
                              // ...
                              long x = (long)m.LParam;
                              MessageBox.Show("It worked:  " + x.ToString());
                              return true;
                        }
                        case WM_USER + 2:
                        {
                              // Process Custom Message 2
                              // ...
                              return true;
                        }
                        default:
                        {
                              return false;
                        }
                  }
            }
      }
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            private System.ComponentModel.IContainer components;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.components = new System.ComponentModel.Container();
                  this.timer1 = new System.Windows.Forms.Timer(this.components);
                  //
                  // timer1
                  //
                  this.timer1.Enabled = true;
                  this.timer1.Interval = 5000;
                  this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
                  this.ClientSize = new System.Drawing.Size(292, 260);
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.Load += new System.EventHandler(this.Form1_Load);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  System.Windows.Forms.Application.AddMessageFilter( new UserMessageFilter() );
                  Application.Run(new Form1());
            }

            private const int WM_USER = 0x0400;      // C:\PF\MVS.NET2003\VC7\PlatFormSDK\Include\WinUser.h
            private const int WM_NULL = 0x0000;
            private System.Windows.Forms.Timer timer1;
            private const int WM_CUSTOM_MSG = WM_USER + 1;

            [DllImport("user32.dll", SetLastError = true)]
            static extern long PostMessage(long hwnd, long wMsg, long wParam, long lParam);

            [DllImport("user32.dll", SetLastError = true)]
            static extern long SendMessage(long hwnd, long wMsg, long wParam, long lParam);
      
            [DllImport("user32.dll", SetLastError = true)]
            static extern long PostThreadMessage(uint uiThreadId, long wMsg, long wParam, long lParam);

            private void Form1_Load(object sender, System.EventArgs e)
            {
                  Class2 c2 = new Class2( (long)this.Handle, (uint)AppDomain.GetCurrentThreadId() );
                  Thread TestThread = new Thread(new ThreadStart( Class2.TestRoutine ) );
//                  timer1.Enabled = true;
                  TestThread.Start();
            }
      
            private void timer1_Tick(object sender, System.EventArgs e)
            {
//                  MessageBox.Show("Main Thread Id is: " + AppDomain.GetCurrentThreadId().ToString());
//                  PostThreadMessage( (uint)AppDomain.GetCurrentThreadId(), WM_CUSTOM_MSG, 0, 0);
                  PostMessage( (long)this.Handle, WM_CUSTOM_MSG, 0, 0);
            }

      }

      public class Class2
      {
            [DllImport("user32.dll", SetLastError = true)]
            static extern long PostMessage(long hwnd, long wMsg, long wParam, long lParam);

            [DllImport("user32.dll", SetLastError = true)]
            static extern long SendMessage(long hwnd, long wMsg, long wParam, long lParam);
      
            [DllImport("user32.dll", SetLastError = true)]
            static extern long PostThreadMessage(uint uiThreadId, long wMsg, long wParam, long lParam);

            private const int WM_USER = 0x0400;      // C:\PF\MVS.NET2003\VC7\PlatFormSDK\Include\WinUser.h
            private const int WM_NULL = 0x0000;
            private const int WM_CUSTOM_MSG = WM_USER + 1;
            
            public static long _Handle;
            public static uint uiThreadID;

            public Class2(long Handle, uint tid)
            {
                  _Handle = Handle;
                  uiThreadID = tid;
            }
            public static void TestRoutine()
            {
                  while( true )
                  {
                        PostMessage( _Handle, WM_CUSTOM_MSG, 0, 0 );
//                        PostThreadMessage( uiThreadID, WM_CUSTOM_MSG, (long)1234, 0 );
                        MessageBox.Show("My Thread Id is: " + AppDomain.GetCurrentThreadId().ToString());
                        Thread.Sleep( 5000 );
                  }
            }
      }
}
0
 
eternal_21Commented:
At a minimum, make these 2 changes:

Class2:

  static extern long PostMessage(long hwnd, long wMsg, long wParam, long lParam);
->
  static extern int PostMessage(int hwnd, int wMsg, int wParam, int lParam);

Class2.TestRouting:

  PostMessage( _Handle, WM_CUSTOM_MSG, 0, 0 );
->
  PostMessage( (int)_Handle, WM_CUSTOM_MSG, 0, 0 );

But you really need to correct the declarations for all your external functions (they should be using int (Int32), not long (Int64), for parameters and return types).
0
 
divyakolusAuthor Commented:
Let me try that. Just for the ...
0
 
divyakolusAuthor Commented:
GREAT!! YOU ARE RIGHT ABOUT THAT. THANK YOU.

I am having another problem. Since the application worked with PostThreadMessage(), I let the application run for a while. It runs for short period of time and generates a Win32 exception and terminates. I can't even do any troubleshooting. It displays a dialog box asking whether to report the error to Microsoft or not.
It says the error is coming from ntdll.dll. It says JIT debugging is disabled. But all the options are enabled in the editor. I know it is very very typical question for you. But if you happen to come across this type, please let me know.

Thank you for the help,
0
 
eternal_21Commented:
First, change your PostThreadMessage like I suggested to ints, instead of uints/longs.  Then, run your program for a while again - let me know if it crashes... I don't know if it will make a difference, but now I am curious!
0
 
divyakolusAuthor Commented:
I am still getting that "Unhandled Win32 Exception". It also says something like "A debugger that can not handle the exception has been attached". I don't what the hell it is trying to say in the later sentense. Anyway it is still crashing.
0
 
eternal_21Commented:
I just ran it for about 10 minutes, and didn't get an error.  Sorry, all I can suggest is try it on another computer, or post a message in "Win Prog" or the "C++" topic areas and see if someone there can help you...
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 8
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now