I'm creating a Selenium bot as a WPF application. I'm using Tasks to create bots and then tasks to perform things on bot.
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);
}
I have array of accounts and I loop through them.
Let's say accounts.Length = 10
=> I want to create 10 tasks that will 'have their own life' and run async inside of them. My problem is that Tasks wait for each other. Loop will create 10 tasks gradually (because of Task.Delay(600)
) => Bot will be created and start bot.Connect();
Lets say it takes always same amount of time to complete Connect()
.
Logically first Task should be completed 600ms faster than second Task. Problem is that program waits until all Connect()
are completed. Then it starts gradually all SendTokens()
then complete them, but first task won't start SayHi()
until SendTokens()
of last bot in list is completed.
Why is that happening, I don't understand that. I tried setting
ThreadPool.SetMaxThreads(500, 500);
but that does nothing for me.
Here is example of live debug output, starts LoadOptions()
gradually many times, but first LoadOptions()
should be already completed and next method should be already started but it is waiting for all LoadOptions
to end. I don't use in code Task.WaitAll()
.
Can anyone help me fix this issue and tell me what was wrong? I want to learn and know in future. Thank you very much and have a nice day.
As I understand it, your loop launches N bots and starts them on a "Life of their own" . The loop provides a spacing of 600 ms between Bot
launches. The Bot
class contains various async
tasks, and for any given Bot
there is an example start sequence of Connect
, SendTokens
, and SayHi
where each of these three methods must complete before the next one starts.
But apart from that, each bot should be taking care of its own internal tasks concurrently while other bots are taking care of theirs. A typical concurrent timeline might look like this:
Here's one approach you could try to achieve this outcome. If the Bot
class comes from a library where it can't be modified you can still make an async
Extension method for it instead. (I'll show it that way just in case. Otherwise just make it a normal method of the Bot
class.) Note that the return type is void
; the Bot
has a life of its own per your post! We don't wait for it to live its life. HOWEVER it has internal business where one async
activity must run to completion before the next one starts, and this extension method accounts for that.
static class Extensions
{
public static async void PostInitAsyncRequest(this BlackBoxBot bot)
{
await bot.Connect();
await bot.SendTokens();
await bot.SayHi();
}
}
All your WPF
application needs to do is call the launchAllBots
method which waits 600 ms between launches.
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);
}
}
SIMULATION In order to mock this startup timeline, the following fake Bot
class was used:
// 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; }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.