簡體   English   中英

異步方法在同一線程上運行,沒有時間延遲

[英]Async methods running on same thread with no time delay

這是AsyncMethods類的樣子:

public class AsyncMethods
{
    public static async Task<double> GetdoubleAsync()
    {
        Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId);
        await Task.Delay(1000);
        return 80d;
    }
    public static async Task<string> GetStringAsync()
    {
        Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId);
        await Task.Delay(1000);
        return "async";
    }
    public static async Task<DateTime> GetDateTimeAsync()
    {
        Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId);
        await Task.Delay(1000);
        return DateTime.Now;
    }
}

我的主要方法如下所示:

static void Main(string[] args)
{
    while (Console.ReadLine() != "exit")
    {
        Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId);
        DateTime dt = DateTime.Now;
        var res = GetStuffAsync().Result;
        var ts = DateTime.Now - dt;
        Console.WriteLine(res);
        Console.WriteLine("Seconds taken: " + ts.Seconds + " milliseconds taken: " + ts.Milliseconds);
    }
    Console.ReadLine();
    return;
}
static async Task<object> GetStuffAsync()
{
    var doubleTask = AsyncMethods.GetdoubleAsync();
    var StringTask = AsyncMethods.GetStringAsync();
    var DateTimeTask = AsyncMethods.GetDateTimeAsync();

    return new
    {
        _double = await doubleTask,
        _String = await StringTask,
        _DateTime = await DateTimeTask,
    };
}

從每種方法可以看出,我增加了1秒的延遲。 這是輸出:

Thread.CurrentThread.ManagedThreadId: 10
Thread.CurrentThread.ManagedThreadId: 10
Thread.CurrentThread.ManagedThreadId: 10
Thread.CurrentThread.ManagedThreadId: 10
{ _double = 80, _String = async, _DateTime = 2/15/2017 4:32:00 AM }
Seconds taken: 1 milliseconds taken: 40

Thread.CurrentThread.ManagedThreadId: 10
Thread.CurrentThread.ManagedThreadId: 10
Thread.CurrentThread.ManagedThreadId: 10
Thread.CurrentThread.ManagedThreadId: 10
{ _double = 80, _String = async, _DateTime = 2/15/2017 4:32:03 AM }
Seconds taken: 1 milliseconds taken: 16

現在我有2個問題:

  1. 一切如何在單個線程上發生?
  2. 為什么等待3秒時延遲只有1秒?

首先,如果您有兩個問題, 請問兩個問題 不要在一個問題中提出兩個問題。

一切如何在單個線程上發生?

這是個錯誤的問題。 正確的問題是:您為什么認為第二個線程應該發生任何事情?

在這里,我將給您一個任務:等待五分鍾,然后檢查您的電子郵件。 在等待時,做一個三明治。 您是否需要雇用某人來做等待或做三明治 顯然不是。 線程是工人。 如果工作可以由一名工人完成,則無需雇用一名工人。

await的全部目的是避免在不需要時使用額外的線程。 在這種情況下,您不需要。

為什么等待3秒時延遲只有1秒?

比較這兩個工作流程。

  • 等待五分鍾; 在等你的時候,做一個三明治
  • 然后檢查您的電子郵件
  • 然后等待五分鍾; 在等你的時候,做一個三明治
  • 然后檢查您的電子郵件
  • 然后等待五分鍾; 在等你的時候,做一個三明治
  • 然后檢查您的電子郵件

如果執行該工作流程,則總共要等待15分鍾。

您編寫的工作流程為:

  • 等五分鍾
  • 同時,等待五分鍾
  • 同時,等待五分鍾
  • 在等你的時候,做一個三明治
  • 然后檢查您的電子郵件

您只需等待五分鍾即可完成該工作流程。 所有延遲都在同一時間發生。

您是否看到現在錯誤地編寫程序的方式?

在這里要理解的關鍵見解是, 等待是程序中的一點,其中等待的持續時間被延遲到等待任務完成之后

如果您不等待,程序將自動繼續運行而無需等待。 那就是await的意思。

它們都同一線程開始 當您依次調用三個Async方法時,它們都將同步執行直到第一個await調用。 (在await ,它們成為狀態機,它們在計划調度時會停下來。如果在await Task.Delay調用之后檢查線程ID,您可能會發現延續在不同的線程上運行-至少在控制台應用程序中)。

至於為什么只延遲1秒鍾...這就是您要告訴它執行的操作。 您有三個異步任務,它們同時運行,每個任務都延遲一秒鍾。 您並不是說“等到第一個任務完成后再開始第二個任務”,實際上,您正在認真地做相反的事情,先啟動所有三個,然后等待所有三個,以便它們並行運行。

您的Console.WriteLine()調用GetdoubleAsync(),GetStringAsync()和GetDateTimeAsync()發生在調用線程中,因為它們發生在第一次繼續之前。

您的等待Task.Delay()調用使線程返回到調用代碼。

當Task.Delay()返回的任務完成時,這些Task的繼續執行返回其值並將其任務設置為已完成。

這允許您在GetStuffAsync()中等待3個(按順序,同步順序)返回。 每個人都必須等待1秒鍾才能標記為已完成,但是它們同時在屈服和發生。

我認為您正在尋找System.Threading.Tasks.Parallel同時執行操作。 異步...等待對於產生線程很有用。

您要同時啟動所有任務,因此它們將並行運行,而不是依次運行。 這就是為什么一切都在1000毫秒后完成。

此外, async不會創建新線程,而是異步使用當前線程。 您可以在異步javascript(這是一個單線程環境)或Unity3D中的協程中看到這種行為。 它們都允許沒有線程的異步行為。

因此,您的每個任務都在同一線程上運行,並在1秒內完成。

暫無
暫無

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

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