簡體   English   中英

任務相互等待完成

[英]Tasks wait for each other to complete

我正在創建一個 Selenium 機器人作為 WPF 應用程序。 我正在使用任務來創建機器人,然后使用任務在機器人上執行任務。

        foreach (string account in accounts)
        {
            count++;

            _ = Task.Run(async () =>
            {
                Bot bot = new Bot();

               //here is long code for what should bot do ASYNC

               //example
                await bot.Connect();                   
                await bot.SendTokens(); 
                await bot.SayHi(); 
            });
            await Task.Delay(600);
        }

我有一系列帳戶,我遍歷它們。

假設accounts.Length = 10 => 我想創建 10 個“擁有自己的生活”並在其中運行異步的任務。 我的問題是任務相互等待。 Loop 將逐漸創建 10 個任務(因為Task.Delay(600) )=> Bot 將被創建並啟動bot.Connect(); 可以說完成Connect()總是需要相同的時間。

從邏輯上講,第一個任務應該比第二個任務快 600 毫秒。 問題是程序一直等到所有Connect()都完成。 然后它逐漸啟動所有SendTokens()然后完成它們,但第一個任務不會啟動SayHi()直到列表中最后一個機器人的SendTokens()完成。

為什么會這樣,我不明白。 我試過設置

ThreadPool.SetMaxThreads(500, 500);

但這對我沒有任何幫助。

這是實時調試輸出的示例,逐步啟動LoadOptions()多次,但第一個LoadOptions()應該已經完成​​,下一個方法應該已經啟動,但它正在等待所有LoadOptions結束。 我不在代碼Task.WaitAll()中使用。

調試輸出

誰能幫我解決這個問題並告訴我出了什么問題? 我想在未來學習和了解。 非常感謝,祝您有愉快的一天。

據我了解,您的循環會啟動 N 個機器人並以“自己的生活”啟動它們。 該循環在Bot啟動之間提供 600 毫秒的間隔。 Bot類包含各種async任務,對於任何給定的Bot ,都有一個ConnectSendTokensSayHi的示例啟動序列,其中這三個方法中的每一個都必須在下一個方法開始之前完成。

但除此之外,每個機器人應該同時處理自己的內部任務,而其他機器人則在處理它們的內部任務。 典型的並發時間線可能如下所示:

並發時間線

這是您可以嘗試實現此結果的一種方法。 如果Bot類來自無法修改的庫,您仍然可以為其創建async擴展方法。 (以防萬一,我會以這種方式顯示。否則,只需將其Bot類的普通方法。)請注意,返回類型是void 根據您的帖子, Bot有自己的生命! 我們不會等待它過上它的生活。 然而,它有內部業務,其中一個async活動必須在下一個活動開始之前運行完成,而這種擴展方法說明了這一點。

static class Extensions
{
    public static async void PostInitAsyncRequest(this BlackBoxBot bot)
    {
        await bot.Connect();
        await bot.SendTokens();
        await bot.SayHi();
    }
}

您的WPF應用程序需要做的就是調用launchAllBots方法,該方法在兩次啟動之間等待 600 毫秒。

async void launchAllBots() 
{
    foreach (string account in new string[] 
    {"Jessie", "Ross", "Kensho", "Ernest", "Amy", "Andrew", "Baxter", "Jibo", "Buddy"})
    { 
        // Has its own life so DO NOT AWAIT
        var bot = new BlackBoxBot();
        bot.Account = account;
        bot.PostInitAsyncRequest();

        // But DO await the delay to space out Bot launches
        await Task.Delay(600);          
    }
}

模擬為了模擬這個啟動時間線,使用了以下假Bot類:

// A crude mock of the 'Bot' class with internal async methods.
class BlackBoxBot
{
    public async Task Connect() 
    {
        Console.WriteLine($"{DateTime.Now.ToString("ss:fff")} {Account}: {nameof(Connect)}");
        await Task.Delay(_rando.Next(400, 800));
    }
    public async Task SendTokens()
    {
        Console.WriteLine($"{DateTime.Now.ToString("ss:fff")} {Account}: {nameof(SendTokens)}");
        await Task.Delay(_rando.Next(400, 800));
    }
    public async Task SayHi()
    {
        Console.WriteLine($"{DateTime.Now.ToString("ss:fff")} {Account}: {nameof(SayHi)}");
        await Task.Delay(_rando.Next(400, 800));
    }

    static Random _rando = new Random();

    public string Account { get; internal set; }
}

暫無
暫無

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

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