繁体   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