免责声明:我发布这个答案只是因为它满足了提问者的要求,而且我并没有从Servy那里抄袭: 你无能为力。但是我建议不要在生产环境中使用这个。个人建议是放弃使用那个库,自己实现。
话虽如此,作为一个测试,我创建了一个包含一个方法DoWork
的类库,该方法会启动一个后台线程,并运行10秒钟:
public class ThirdParty
{
public static void DoWork()
{
new Thread(() => Thread.Sleep(10000)) { IsBackground = true }.Start();
}
}
现在的想法是在调用
ThirdParty.DoWork
之前和之后比较运行的线程。在调用之后,将收集一个或多个线程ID,并使用
OpenThread
将其转换为线程句柄。最后,您可以调用
WaitForMultipleObjects
等待第三方后台线程完成其工作。
class Program
{
[DllImport("kernel32.dll")]
static extern uint WaitForMultipleObjects(int nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds);
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, int dwThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
const uint SYNCHRONIZE = 0x00100000;
static IntPtr GetThreadHandleById(int threadId)
{
return OpenThread(SYNCHRONIZE, false, threadId);
}
static void Main(string[] args)
{
var threads = new List<int>();
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
threads.Add(thread.Id);
ThirdParty.DoWork();
var threadHandlesToWaitFor = new List<IntPtr>();
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
if (!threads.Contains(thread.Id))
threadHandlesToWaitFor.Add(GetThreadHandleById(thread.Id));
Console.WriteLine("Waiting for {0} thread(s) to finish...", threadHandlesToWaitFor.Count);
WaitForMultipleObjects(threadHandlesToWaitFor.Count, threadHandlesToWaitFor.ToArray(), true, 0xffffffff);
foreach (var handle in threadHandlesToWaitFor)
CloseHandle(handle);
}
}
实质上,我们正在等待一个似乎在衍生的托管线程上运行的非托管线程。这可能会在未来发生故障,因为.NET不能保证每个托管线程都在自己的非托管线程上运行。
Process.GetCurrentProcess().Threads
也无法帮助,因为它获取的是非托管线程,而它们与托管线程之间的对应关系很难确定。我不认为有什么方法可以解决这个问题。 - Ian Mercer