I did a little poking around in the debugger and came up with some "working
code" that you might want to take and run with.  Obviously, solutions like
this are highly coupled to the current build of the runtime, so always
remember that you get what you pay for; and that this is free code :-)

The solution is based on observing how the where the Thread class stores the
underlying native Win32 thread HANDLE, using reflection and pointer
arithmetic to grab it, and then using that fetched handle to construct a
custom WaitHandle derived class that you can use like any other WaitHandle.

Here's the code (which works on XP Pro using SP1 of the .NET FW):

public class ThreadWaitHandle : WaitHandle
{
    public ThreadWaitHandle()
        : this(Thread.CurrentThread)
    {
    }

    public ThreadWaitHandle( Thread targetThread )
    {
        Handle = GetManagedCurrentThreadHandle(targetThread);
    }

    public unsafe static IntPtr GetManagedCurrentThreadHandle( Thread
targetThread )
    {
        // The following has been observed for SP1 of the .NET Framework:
        //
        // A Thread instance has a private IntPtr field
(DONT_USE_InternalThread)
        // that is a pointer to a structure describing the thread.  The
HANDLE
        // to the underlying native Win32 thread object is stored at the
32bit
        // field located at byte offset 0xAC from the top of that structure
        // (the 43rd dword).
        //

        // Lookup the FieldInfo for the DONT_USE_InternalThread field.
        //
        FieldInfo fi =
            typeof(Thread).GetField( "DONT_USE_InternalThread",
                                    BindingFlags.Instance |
BindingFlags.NonPublic );

        if( fi == null )
            return new IntPtr(0);

        // Fetch the value of that field and grab the 43rd dword (+ 0xAC).
        //
        IntPtr ThreadInfoPtr = (IntPtr)fi.GetValue(targetThread);
        int hThread = ((int *)ThreadInfoPtr.ToPointer())[43];

        // TODO: do a proper DuplicateHandle of that field, then override
        // Close/Dispose on WaitHandle and do a proper CloseHandle.

        return new IntPtr(hThread);
    }

    public static IntPtr GetManagedCurrentThreadHandle()
    {
        return GetManagedCurrentThreadHandle(Thread.CurrentThread);
    }
}

You'll need to throw the /unsafe compiler switch to use the above class.
Usage model is this:

Thread t1 = new Thread(...);
t1.Start();
Thread t2 = new Thread(...);
t2.Start();

WaitHandle[] threadHandles =
    {new ThreadWaitHandle(t1), new ThreadWaitHandle(t2)};
WaitHandle.WaitAll(threadHandles);

-Mike
http://staff.develop.com/woodring
http://www.develop.com/devresources

----- Original Message -----
From: "Mike Woodring" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Friday, April 19, 2002 6:16 PM
Subject: Re: [DOTNET] Waiting for multiple Threads


> Unfortunately, that's as good as it gets right now.  When we asked almost
> two years ago about this on this list, the answer was, "we'll look into
it".
> But it looks like it was one of those things that fell through the cracks.
> The docs at the time said that the Thread class would itself extend the
> WaitHandle base class, allowing you to do a WaitMultiple on them, but they
> never got around to actually building it that way...
>
> -Mike
> http://staff.develop.com/woodring
> http://www.develop.com/devresources
>
> ----- Original Message -----
> From: "Murphy, James" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Thursday, April 18, 2002 8:40 AM
> Subject: Re: [DOTNET] Waiting for multiple Threads
>
>
> > Provided the threads are at least started you can call join sequentially
> on
> > the collection of thread objects...
> >
> > ArrayList threads;
> > ...
> >
> > foreach (Thread t in threads)
> >    t.Join();
> >
> > Should work though I haven't tried it :)
> >
> > Jim
> >
> > > -----Original Message-----
> > > From: Diego Gonzalez [mailto:[EMAIL PROTECTED]]
> > > Sent: Thursday, April 18, 2002 9:18 AM
> > > To: [EMAIL PROTECTED]
> > > Subject: Re: [DOTNET] Waiting for multiple Threads
> > >
> > >
> > > But WaitAll() receives a WaitHandle[], and i don't know how to get the
> > > Thread hanlde in order to wait for it.Using Join() allows the
> > > current thread
> > > to wait for another thread, i wanted to wait for multiple threads.
> > >
> > > Diego
> > >
> > > ----- Original Message -----
> > > From: "Nick Wienholt" <[EMAIL PROTECTED]>
> > > To: <[EMAIL PROTECTED]>
> > > Sent: Wednesday, April 17, 2002 11:47 PM
> > > Subject: Re: [DOTNET] Waiting for multiple Threads
> > >
> > >
> > > > Hi Diego,
> > > >
> > > > If you are waiting for the threads to terminate, use Thread.Join.
> > > > Otherwise, WaitHandle.WaitAll is the System.Threading equivalent to
> > > > WaitForMultipleObjects.
> > > >
> > > > Nick
> > > >
> > > > ----- Original Message -----
> > > > From: "Diego Gonzalez" <[EMAIL PROTECTED]>
> > > > To: <[EMAIL PROTECTED]>
> > > > Sent: Thursday, April 18, 2002 3:35 AM
> > > > Subject: [DOTNET] Waiting for multiple Threads
> > > >
> > > >
> > > > > Is there any way to wait for multiple running Threads? I will call
> > > > > WaitForMultipleObjects, but there is no way to get the
> > > thread handle.
> > > > >
> > > > > Diego
> > > > >
> > > > > You can read messages from the DOTNET archive,
> > > unsubscribe from DOTNET,
> > > or
> > > > > subscribe to other DevelopMentor lists at
> > http://discuss.develop.com.
> > > >
> > >
> > > You can read messages from the DOTNET archive, unsubscribe from
DOTNET,
> or
> > > subscribe to other DevelopMentor lists at http://discuss.develop.com.
> > >
> >
> > You can read messages from the DOTNET archive, unsubscribe from DOTNET,
or
> > subscribe to other DevelopMentor lists at http://discuss.develop.com.
> >
> > You can read messages from the DOTNET archive, unsubscribe from DOTNET,
or
> > subscribe to other DevelopMentor lists at http://discuss.develop.com.
> >
>
> You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
> subscribe to other DevelopMentor lists at http://discuss.develop.com.
>

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to