Proceed. The clutch does not work properly

I have an example code:

static void Main(string[] args) { var t1 = Task.Run(async () => { Console.WriteLine("Putting in fake processing 1."); await Task.Delay(300); Console.WriteLine("Fake processing finished 1. "); }); var t2 = t1.ContinueWith(async (c) => { Console.WriteLine("Putting in fake processing 2."); await Task.Delay(200); Console.WriteLine("Fake processing finished 2."); }); var t3 = t2.ContinueWith(async (c) => { Console.WriteLine("Putting in fake processing 3."); await Task.Delay(100); Console.WriteLine("Fake processing finished 3."); }); Console.ReadLine(); } 

The console exit illuminates me:

  • Entering Fake Processing 1.
  • Fake processing 1 completed.
  • Enter fake processing 2.
  • Fake Processing 3.
  • Fake Processing 3 completed.
  • Forged processing completed 2.

I am trying to link tasks so that they are performed one by one, what am I doing wrong? And I can’t use the wait, this is just an example of the code, in fact I perform the next tasks (some asynchronous, some not) and I want to execute them in the same order as they entered, but without parallelism, ContinueWith seemed better than creating ConcurrentQueue and handle everything, but it just doesn't work ...

+5
source share
2 answers

Take a look at type t2 . This is a Task<Task> . t2 will be completed when it finishes completing the task performing the actual work, when this work is not completed.

The smallest change to your code to make it work would be to add unwrap after the second and third calls to ContinueWith so that you select a task that represents the completion of your work.

A more idiomatic solution would be to simply remove ContinueWith calls completely and just use await to add continuations to tasks.

Interestingly, you would see the same behavior for t1 if you used Task.Factory.StartNew , but Task.Run specifically designed to work with async lambdas and actually expands all Action<Task> delegates internally to return the result of the returned task, and not the task that represents the launch of this task, so you do not need to deploy this task.

+8
source

In reality, I execute a queue for incoming tasks (some asynchronous, some not) and I want to execute them in the same order in which they entered, but without parallelism

You probably want to use the TPL data stream for this. In particular, ActionBlock .

 var block = new ActionBlock<object>(async item => { // Handle synchronous item var action = item as Action; if (action != null) action(); // Handle asynchronous item var func = item as Func<Task>; if (func != null) await func(); }); // To queue a synchronous item Action synchronous = () => Thread.Sleep(1000); block.Post(synchronous); // To queue an asynchronous item Func<Task> asynchronous = async () => { await Task.Delay(1000); }; blockPost(asynchronous); 
+2
source

Source: https://habr.com/ru/post/1201932/


All Articles