I want to start a task after my tasks have gone through five times. Is this possible in a simple way? I can't do that with a simple timer because my customers set the time in the tasks themselves. When I set a timer, the task that is supposed to start after the fifth round starts at the wrong time.
I have a program whose tasks (8 tasks) start and end one after the other. The last task then starts the first again. and I somehow need a counter that counts when the fifth round is over. So the last task must be completed for the fifth time, then this one specific task that I want to include should switch on automatically and if they is done then start the first one itself.
this is my async tasks.. it starts with button and repeats.. its only a minimized version.
async void STARTCLICK(CancellationToken token)
{
for (int i = 0; i < 2; i )
{
try
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
if ()
{
}
}
catch (AggregateException)
{
MessageBox.Show("Expected");
}
catch (ObjectDisposedException)
{
MessageBox.Show("Bug");
}
catch { }
}
Thread.Sleep(2000);
var t2 = Task.Run(() => START(token));
await Task.WhenAny(new[] { t2 });
}
async void START(CancellationToken token)
{
for (int i = 0; i < 10; i )
{
try
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
if ()
{
}
}
catch (AggregateException)
{
Console.WriteLine("Expected");
}
catch (ObjectDisposedException)
{
Console.WriteLine("Bug");
}
catch { }
}
Thread.Sleep(7000);
var t3 = Task.Run(() => MOVE(token));
await Task.WhenAny(new[] { t3 });
}
async void MOVE(CancellationToken token)
{
for (int i = 0; i < 4; i )
{
try
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
if ()
{
}
}
catch (AggregateException)
{
Console.WriteLine("Expected");
}
catch (ObjectDisposedException)
{
Console.WriteLine("Bug");
}
catch { }
}
var t4 = Task.Run(() => RESTART(token));
await Task.WhenAny(new[] { t4 });
}
async void RESTART(CancellationToken token)
{
for (int i = 0; i < 4; i )
{
try
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
if ()
{
}
}
catch (AggregateException)
{
Console.WriteLine("Expected");
}
catch (ObjectDisposedException)
{
Console.WriteLine("Bug");
}
catch { }
}
var t4 = Task.Run(() => STARTCLICK(token));
await Task.WhenAny(new[] { t4 });
CodePudding user response:
The way that you have implemented the infinite recursive loop is a bit sketchy. It should be quite difficult to maintain it. My suggestion is to remove the dependencies/interactions between the asynchronous methods, and delegate the responsibility of calling them in a looping fashion to a "master" asynchronous method, that invokes them sequentially in a while
loop:
async Task InfiniteLoopAsync()
{
long iteration = 0;
while (true)
{
iteration ;
await Method_A();
await Method_B();
await Method_C();
await Method_D();
if (iteration % 5 == 0) await Method_E();
}
}
Each of the methods should have a Task
return type, not void
:
async Task Method_A()
{
}
Finally you can start the infinite loop like this:
private async void Button1_Click(object sender, EventArgs args)
{
await InfiniteLoopAsync();
}
The Click
event handler should be your only method with async void
signature.
CodePudding user response:
Use a SemaphoreSlim
with a max count of 5. This means a maximum of 5 threads can enter this semaphore at once. Once all five is consumed, perform the special task and release 5 threads on the semaphore. Rinse and repeat.
Here is an example. Warning: the TaskRepeater
class is faulty (e.g. exception handling).
using System;
using System.Threading;
using System.Threading.Tasks;
var taskRepeater = new TaskRepeater(async () => await RepeatedTaskAsync(), 5);
await taskRepeater.RunAsync(async () => await RegularTaskAsync("A"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("B"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("C"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("D"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("E"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("F"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("G"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("H"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("I"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("J"));
await taskRepeater.RunAsync(async () => await RegularTaskAsync("K"));
static async Task RepeatedTaskAsync()
{
Console.WriteLine("Running repeated task.");
await Task.Delay(500);
}
static async Task RegularTaskAsync(string id)
{
Console.WriteLine($"Running regular task {id}.");
await Task.Delay(50);
}
public class TaskRepeater
{
private readonly int frequency;
private readonly Func<Task> repeatTaskFactory;
private readonly SemaphoreSlim semaphore;
private readonly SemaphoreSlim repeatSemaphore;
public TaskRepeater(Func<Task> repeatTaskFactory, int frequency)
{
this.frequency = frequency;
this.repeatTaskFactory = repeatTaskFactory;
this.semaphore = new SemaphoreSlim(frequency, frequency);
this.repeatSemaphore = new SemaphoreSlim(1, 1);
}
public async Task RunAsync(Func<Task> taskFactory)
{
try
{
await this.semaphore.WaitAsync();
await taskFactory.Invoke();
if (this.semaphore.CurrentCount == 0 && this.repeatSemaphore.CurrentCount != 0)
{
await this.PerformRepeatedTaskAsync();
}
}
catch (Exception)
{
if (this.semaphore.CurrentCount == 0)
{
this.semaphore.Release();
}
if (this.repeatSemaphore.CurrentCount > 0)
{
this.repeatSemaphore.Release();
}
throw;
}
}
private async Task PerformRepeatedTaskAsync()
{
await this.repeatSemaphore.WaitAsync();
if (this.semaphore.CurrentCount > 0)
{
this.repeatSemaphore.Release();
return;
}
await this.repeatTaskFactory.Invoke();
this.semaphore.Release(frequency);
this.repeatSemaphore.Release();
}
}
This outputs:
Running regular task A.
Running regular task B.
Running regular task C.
Running regular task D.
Running regular task E.
Running repeated task.
Running regular task F.
Running regular task G.
Running regular task H.
Running regular task I.
Running regular task J.
Running repeated task.
Running regular task K.