簡體   English   中英

C#異步等待從未返回主線程

[英]C# Async Await never returns to main thread

我寫了一個非常簡單的檢查,告訴我我在哪個線程上,然后添加了一些異步等待代碼。 我注意到,我第一次檢查自己在線程1上,然后在線程3上,並且在執行代碼期間我從未返回線程1。

誰能向我解釋為什么在等待之后我不返回到調用等待的主線程? WhatThreadAmI()的輸出如下:

**********************
Main - 17 -- True
**********************
**********************
CountAsync - 37 -- False
**********************
**********************
Main - 22 -- False
**********************
**********************
Main - 29 -- False
**********************

示例代碼:

class Program
{
    static Thread mainThread;
    public static async Task Main(string[] args)
    {
        mainThread = Thread.CurrentThread;


        WhatThreadAmI();

        Console.WriteLine("Counting until 100 million in 5 seconds ...");
        var msWait = await CountAsync();

        WhatThreadAmI();
        Console.WriteLine($"Counting to 100 million took {msWait} milliseconds.");


        Console.WriteLine("Press any key to exit");
        Console.ReadKey();

        WhatThreadAmI();
    }


    static async Task<String> CountAsync()
    {
        return await Task.Run(() =>
        {
            WhatThreadAmI();
            Task.Delay(TimeSpan.FromSeconds(5)).Wait();
            var startTime = DateTime.Now;

            var num = 0;

            while (num < 100000000)
            {
                num += 1;
            }

            return (DateTime.Now - startTime).TotalMilliseconds.ToString();

        });
    }


    static void WhatThreadAmI([CallerMemberName]string Method = "", [CallerLineNumber]int Line = 0)
    {
        const string dividor = "**********************";

        Debug.WriteLine(dividor);
        Debug.WriteLine($"{Method} - {Line} -- {IsMainThread()}");
        Debug.WriteLine(dividor);
    }

    public static bool IsMainThread() => mainThread == Thread.CurrentThread;

}

await將捕獲當前的同步上下文( SynchronizationContext.Current )並將后續過程( await之后的所有內容)發布到該上下文中(除非您使用ConfigureAwait(false) )。 如果沒有同步上下文,例如在控制台應用程序中(在您的情況下)-默認情況下,將繼續計划線程池線程的繼續。 您的主線程不是線程池線程,因此您永遠不會在發布的代碼中返回它。

注意,每個同步上下文實現都可以決定如何處理發布到其上的回調,而不必將回調發布到單線程中(就像WPF \\ WinForms同步上下文一樣)。 因此,即使使用同步上下文,也不能保證“返回到調用者線程”。

即使您現在可以具有異步主要功能,但控制台應用程序仍沒有OperationContext。 因此,它將使用默認的任務計划程序,這將導致在等待使用任何線程池線程而不是與OperationContext關聯的原始線程后繼續執行。

暫無
暫無

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

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