簡體   English   中英

等待線程完成

[英]Waiting for threads to complete

我有一個C#程序調用幾個函數,每個函數調用另一個DLL中的方法。 此方法創建一個新線程來完成其工作,然后立即返回。

問題是我需要我的主程序等待所有未完成的線程完成。 我怎么能做到這一點?

我試着谷歌搜索一個答案和我說的所有答案要么使用TPL(我不能因為我使用.NET 3.5)或獲得對線程的引用並使用Thread.Join 但由於線程是在另一個DLL文件中創建的,我沒有源代碼訪問權限,因此該選項也是如此。

我怎么能等待我的所有線程完成?

免責聲明:我發布這個答案只是因為它做了OP所要求的,我沒有接受Servy的回答: 你無能為力 但我建議不要在生產環境中使用它。 就個人而言,我會放棄那個圖書館並自己實施。

這說,作為一個測試,我創建了一個類庫,它包含一個方法DoWork ,它啟動一個運行10秒的后台線程:

public class ThirdParty
{
    public static void DoWork()
    {
        new Thread(() => Thread.Sleep(10000)) { IsBackground = true }.Start();
    }
}

現在,我們的想法是比較ThirdParty.DoWork調用之前和之后的運行線程。 在調用之后,將使用OpenThread收集一個(或多個)線程id並將其轉換為線程句柄。 最后,您可以調用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不保證每個托管線程都在其自己的非托管線程上運行。

也許你可以安裝自定義CLR Profiler。 這使您可以訪問所有托管線程。 你應該能夠攔截幾乎任何東西。 您應該能夠攔截線程啟動和關閉。

SQL Server和ASP.NET等主機使用CLR Profiler API對托管的.NET代碼執行極為侵入式的監視和行為更改。

作為最后的手段,您甚至可以使用Profiler API來運行時重寫該庫的IL ...

這是一種可靠的方法,但可能不容易或快速完成。

鑒於您調用的異步方法沒有提供何時完成( Task ,回調,事件等)的指示,因此您無需執行任何操作。 您總是可以使用這些方法之一將方法重構為另一種方法,但如果核心方法沒有提供何時完成的方法,那么您無能為力。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM