Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MsgWaitForMultipleObjects implementation in C#

723 views
Skip to first unread message

Alexander Galkin

unread,
Jun 4, 2003, 2:35:26 PM6/4/03
to
I need to wait on the worker thread until it exits but processing messages
in the main thread. In Windows programming this can be done with
MsgWaitForMultipleObjects that returns either event one of the sync objects
are signaled or when a message is available in the message queue. How to do
this in C#? Also another but similar question. How to implement a message
pump in C#? I need to process only certain type of messages discarding other
messages. Again in Windows programming I can pump messages with GetMessage
or PeekMessage to get a message out of the queue and then either process it
with DispatchMessage or discard it. Again how to do this in C#?


Mattias Sjögren

unread,
Jun 4, 2003, 9:22:29 PM6/4/03
to
Alexander,

>Also another but similar question. How to implement a message
>pump in C#? I need to process only certain type of messages discarding other
>messages. Again in Windows programming I can pump messages with GetMessage
>or PeekMessage to get a message out of the queue and then either process it
>with DispatchMessage or discard it. Again how to do this in C#?

Normally Windows Forms takes care of setting up the message pump. But
if you have such specific requirements, I guess you could do it all
yourself. You can still call GetMessage et al through P/Invoke.

Mattias

===
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/
Please reply only to the newsgroup.

Dave

unread,
Jun 4, 2003, 10:29:24 PM6/4/03
to
I use the following code with p/invoke to call the win32 api. Perhaps
someone can provide some guidance on how this might be improved, but it
seems to work for me.

private const System.UInt32 QS_KEY = 0x0001;
private const System.UInt32 QS_MOUSEMOVE = 0x0002;
private const System.UInt32 QS_MOUSEBUTTON = 0x0004;
private const System.UInt32 QS_POSTMESSAGE = 0x0008;
private const System.UInt32 QS_TIMER = 0x0010;
private const System.UInt32 QS_PAINT = 0x0020;
private const System.UInt32 QS_SENDMESSAGE = 0x0040;
private const System.UInt32 QS_HOTKEY = 0x0080;
private const System.UInt32 QS_ALLPOSTMESSAGE = 0x0100;
private const System.UInt32 QS_RAWINPUT = 0x0400;
private const System.UInt32 QS_MOUSE = (QS_MOUSEMOVE |
QS_MOUSEBUTTON);
private const System.UInt32 QS_INPUT = (QS_MOUSE |
QS_KEY | QS_RAWINPUT );
private const System.UInt32 QS_ALLEVENTS = (QS_INPUT |
QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY );
private const System.UInt32 QS_ALLINPUT = (QS_INPUT |
QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY |
QS_SENDMESSAGE);
private const System.UInt32 INFINITE = 0xFFFFFFFF; // from winbase.h;
Infinite timeout
private const System.UInt32 STATUS_WAIT_0 = 0;
private const System.UInt32 STATUS_ABANDONED_WAIT_0 = 0x00000080;
private const System.UInt32 WAIT_OBJECT_0 = ((STATUS_WAIT_0 ) +
0 );
private const System.UInt32 WAIT_ABANDONED_0 =
((STATUS_ABANDONED_WAIT_0 ) + 0 );
private const System.UInt32 WAIT_FAILED =
((System.UInt32)0xFFFFFFFF);

[DllImport("user32.dll")]
private static extern System.UInt32 MsgWaitForMultipleObjects(
System.UInt32 nCount, // number of handles in array
System.IntPtr[] pHandles, // object-handle array
bool bWaitAll, // wait option
System.UInt32 dwMilliseconds, // time-out interval
System.UInt32 dwWakeMask // input-event type
);

/// <summary>
/// Invokes system call that waits for an event to get signalled and
/// still processes user input messages.
/// Rtns when the user event gets signalled
/// </summary>
static public bool MsgWaitForSingleObject(IntPtr hEvent)
{
return MsgWaitForSingleObject(hEvent,-1);
}

/// <summary>
/// Invokes system call that waits for an event to get signalled and
/// still processes user input messages.
/// Rtns when the user event gets signalled
/// </summary>
static public bool MsgWaitForSingleObject(IntPtr hEvent,int nTimeout)
{
System.IntPtr[] pHandles = new System.IntPtr[1];
pHandles[0] = hEvent;

System.UInt32 rtn;
while ( true ) // loop forever
{
uint uTimeout;

if ( nTimeout == -1 )
uTimeout = INFINITE;
else
uTimeout = (uint)nTimeout;
rtn = MsgWaitForMultipleObjects(1,pHandles,false,uTimeout,QS_ALLINPUT);
switch ( rtn )
{
case WAIT_OBJECT_0:
return true;
case WAIT_OBJECT_0 + 1: // user input
Application.DoEvents();
break;
default:
return false; // some sort of error
}
}
}


"Alexander Galkin" <aga...@audible.com> wrote in message
news:ugfK3fsK...@TK2MSFTNGP11.phx.gbl...

Alexander Galkin

unread,
Jun 5, 2003, 9:43:50 AM6/5/03
to
Thank you for your response. It just means that FCL does have support for
this and I have to go to API level to implement waiting on handle with
message loop. I see one obstacle however. MsgWaitForMultipleObjects takes
array of HANDLEs to wait on. How do I extract handle from FCL Thread class.

"Dave" <kdle...@wi.rr.com> wrote in message
news:OC$U8owKD...@TK2MSFTNGP12.phx.gbl...

Brian Grunkemeyer [MS]

unread,
Jun 5, 2003, 7:36:13 PM6/5/03
to
Note that WaitHandle's WaitOne and WaitAll methods do pump messsages. We
strongly recommend you do not call any unmanaged synchronization routines
like WaitForSingleObject or any other variants for reliability reasons. The
main problem is if your code is blocked in a Win32 synchronization call like
this, we cannot abort your thread correctly. While our story for thread
abort is not exactly ideal in V1 and V1.1, in a future version we will be
very aggressive about using only managed synchronization primitives for all
Framework code and ideally for all reliable user code. We envision a number
of future hosts for CLR code that may need the ability to safely abort a
thread. (Yes, this is a very hard problem, and yes, this requires new
features and a lot of work. See our next major release.)

--
Brian Grunkemeyer
MS CLR Base Class Library team

This posting is provided "AS IS" with no warranties, and confers no rights.


"Dave" <kdle...@wi.rr.com> wrote in message

news:u8ltjM5...@TK2MSFTNGP11.phx.gbl...
> Actually, the FCL does not have direct support for this...you must use
> p/invoke to get at the underlying API where the support does exist. Also,
> there is no documented means of retrieving the thread handle of an FCL
> thread. However, Mike Woodring of Developmentor wrote a little class that
> uses some undocmented calls to retrieve the native handle of a thread -
it's
> definitely a "use at your own risk" thing. You can get this from the
> Developmentor web site
>
> Dave


>
>
> "Alexander Galkin" <aga...@audible.com> wrote in message

> news:%23x0sph2...@TK2MSFTNGP11.phx.gbl...

Dave

unread,
Jun 5, 2003, 8:32:08 PM6/5/03
to
This would be a very good thing indeed. One of the major issues with the
current implementation of the FCL thread object is the inability to reliably
terminate (i.e. abort) a thread. There currently are requirements that a
thread must satisfy for the abort to succeed which at times are impossible
for managed code to control.


"Brian Grunkemeyer [MS]" <bria...@online.microsoft.com> wrote in message
news:%236yVBt7...@tk2msftngp13.phx.gbl...

Alexander Galkin

unread,
Jun 6, 2003, 12:07:07 AM6/6/03
to
I do not need to pump and process all messages. I need to retrieve ALL
messages from the message queue but process only SOME messages discarding
others. The fact that I cannot utilize major features that OS provides I see
another bad reason to use .NET. I as C++ developer see a huge disadvantage
of FCL as a library. Since I can only use what library provides (what
Microsoft gave me) and cannot use many things that FCL does not provide.
This is a huge contrast with any of C++ libraries (MFC, ATL, STL, WTL). Any
of these libraries provide a lot of functionality, however neither of them
covers everything. So if I want to use something that say ATL does not
provide I can easily do this without any restrictions.

I also don't understand why you (and who is "you") need to abort my thread?

"Brian Grunkemeyer [MS]" <bria...@online.microsoft.com> wrote in message
news:%236yVBt7...@tk2msftngp13.phx.gbl...

Mark Hurd

unread,
Jun 6, 2003, 2:02:11 AM6/6/03
to
Alexander Galkin wrote:
> I do not need to pump and process all messages. I need to retrieve ALL
> messages from the message queue but process only SOME messages discarding
> others. The fact that I cannot utilize major features that OS provides I see
> another bad reason to use .NET. I as C++ developer see a huge disadvantage
> of FCL as a library. Since I can only use what library provides (what
> Microsoft gave me) and cannot use many things that FCL does not provide.
> This is a huge contrast with any of C++ libraries (MFC, ATL, STL, WTL). Any
> of these libraries provide a lot of functionality, however neither of them
> covers everything. So if I want to use something that say ATL does not
> provide I can easily do this without any restrictions.
>
> I also don't understand why you (and who is "you") need to abort my thread?

I think their previous simpler caveat is better here: CLR Thread != Win32
thread.

Coming from VB (and COM), this makes sense as you can find situations where
Win32 synchronisation logic fails because the *same* thread hits two different
instances of a synchronisation object.

That is, while the VB conceptual thread of execution is waiting at a
synchronisation another event occurs and the same thread is used to execute
it!

Given the strong discouragement given to aborting a Win32 thread, I think the
ability to safely abort a managed Thread is going to be a "selling point".

IMHO either the Platform SDK or the .NET Framework SDK (or both) need to
explain which features are just thin wrappers on Win32 features, and will
always be, and how to interface with Win32 features in general -- at a higher
level than just "use P/Invoke".

At this stage, even just a summary page like this:

Threads

Win32 threads are not supported, all handles need to be processed using Win32
routines.

Managed threads may be executed on multiple Win32 threads, and as such there's
no real mapping.


Synchronisation Objects

Because of the threading issue above Managed code should only use Managed
synchronisation objects.

However, named Managed Mutexes are implemented using named Win32 mutexes and
thus can work cross-processes.


Etc.

Regards,
Mark Hurd, B.Sc.(Ma.) (Hons.)


0 new messages