Home > Software design >  How can I run multiple tasks sequentially without blocking the UI?
How can I run multiple tasks sequentially without blocking the UI?

Time:07-13

I'm trying to run these tasks sequentially without any blocking in the UI , however, I've test all methods that I've found but I'm still have a problem , when I get tasks runs without UI block I get a missed steps in the tasks or an infinite running of some tasks .

 public void StartAsync(CancellationToken cancellationToken, string path, int i)
    
    {
        var task1 = Task.Run(() => Task1(path, step, i)); // 
        var task2 = Task.Run(() => Task2(cancellationToken)); // wait for task1 to complete
        var task3 = Task.Run(() => Task3(cancellationToken)); // wait for task2 to complete
        var task4 = Task.Run(() => Task4(cancellationToken, i)); // will call an external process ) ... wait for task3 to complete
        Task.WaitAll(task1, task2, task3, task4);
    }

 public void AnotherTask()
    
    {
        // Some other code ( will call an external process )
    }


 public void RunAllTasks()
    {
       int step = 5;
       cancellationToken = CancellationToken.None;
       string path = "...\\..";
       for (int i = 0;i<step;i  )
        {
             StartAsync(cancellationToken, string path, int i) 
        }

      // wait for StartAsync to complete
       AnotherTask();
    }

private void button_Click(object sender, RoutedEventArgs e) 
    {
        RunAllTasks();
    }

CodePudding user response:

You should await each Task like

public async Task StartAsync(CancellationToken cancellationToken, string path, int i)    
{
    await Task.Run(() => Task1(path, step, i)); 
    await Task.Run(() => Task2(cancellationToken));
    await Task.Run(() => Task3(cancellationToken));
    await Task.Run(() => Task4(cancellationToken, i));
}

or perhaps just call them sequentially in a single Task.Run action, like

public Task StartAsync(CancellationToken cancellationToken, string path, int i)    
{
    return Task.Run(() =>
    {
        Task1(path, step, i); 
        Task2(cancellationToken);
        Task3(cancellationToken));
        Task4(cancellationToken, i);
    });
}

and await the StartAsync call like

public async Task RunAllTasks()
{
     ...
     for (int i = 0;i < step; i  )
     {
         await StartAsync(cancellationToken, path, i);
     }
     ...
}

private async void button_Click(object sender, RoutedEventArgs e) 
{
    await RunAllTasks();
}

In case you want to call StartAsync multiple times in parallel, something like this may also work:

await Task.WhenAll(Enumerable
    .Range(0, 5)
    .Select(i => StartAsync(cancellationToken, path, i)));

CodePudding user response:

You should make use of async/await functionality

 public Task StartAsync(CancellationToken cancellationToken, string path, int i)   
 {
     var task1 = Task.Run(() => Task1(path, step, i)); // 
     var task2 = Task.Run(() => Task2(cancellationToken)); // wait for task1 to complete
     var task3 = Task.Run(() => Task3(cancellationToken)); // wait for task2 to complete
     var task4 = Task.Run(() => Task4(cancellationToken, i)); // will call an external process ) ... wait for task3 to complete
     return Task.WaitAll(task1, task2, task3, task4);
 }

 public void AnotherTask()   
 {
    // Some other code ( will call an external process )
 }


 public async Task RunAllTasks()
 {
    int step = 5;
    cancellationToken = CancellationToken.None;
    string path = "...\\..";
    for (int i = 0;i<step;i  )
    {
        await StartAsync(cancellationToken, string path, int i) 
    }

    // wait for StartAsync to complete
    AnotherTask();
}

private async void button_Click(object sender, RoutedEventArgs e) 
{
    try
    {        
        await RunAllTasks();
    }
    catch(Exception e)
    {   
        //always handle exceptions in async void methods
    }
}
  • Related