?
Solved

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

Posted on 2005-03-10
17
Medium Priority
?
10,607 Views
Last Modified: 2012-05-05
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
Comment
Question by:divyakolus
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 8
17 Comments
 
LVL 1

Expert Comment

by:ariellive
ID: 13508654
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
 

Author Comment

by:divyakolus
ID: 13508735
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
 
LVL 10

Accepted Solution

by:
eternal_21 earned 2000 total points
ID: 13511882
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Expert Comment

by:eternal_21
ID: 13511895
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
 

Author Comment

by:divyakolus
ID: 13511967
Thank you eternal_21.
0
 

Author Comment

by:divyakolus
ID: 13511978
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
 
LVL 10

Expert Comment

by:eternal_21
ID: 13518629
It will work across threads and processes.
0
 
LVL 10

Expert Comment

by:eternal_21
ID: 13518693
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
 

Author Comment

by:divyakolus
ID: 13518698
I don't why but POSTMESSAGE function won't work even on the same thread. PostThreadMessage works. Do you know why??
0
 
LVL 10

Expert Comment

by:eternal_21
ID: 13520080
Can you post your PostMessage code?
0
 

Author Comment

by:divyakolus
ID: 13520292
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
 
LVL 10

Expert Comment

by:eternal_21
ID: 13520478
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
 

Author Comment

by:divyakolus
ID: 13520493
Let me try that. Just for the ...
0
 

Author Comment

by:divyakolus
ID: 13520576
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
 
LVL 10

Expert Comment

by:eternal_21
ID: 13520664
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
 

Author Comment

by:divyakolus
ID: 13520822
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
 
LVL 10

Expert Comment

by:eternal_21
ID: 13521217
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

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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses
Course of the Month11 days, 20 hours left to enroll

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question