简体   繁体   中英

task.continuewith vs dataflow in c#

I have started learning TPL Dataflow . I'm trying hard to find the difference between Task.ContinueWith and dataflow. Below are the two samples codes which has the same objective. First is done with Task.ContinueWith and later with dataflow.
Below is the example with Task.ContinueWith

var tk1 = Task.Run(() =>
{
    Console.WriteLine("Entered 1st Task");
    Thread.Sleep(3000);
    return 2;
});

tk1.ContinueWith((t) =>
{
    Console.WriteLine("Entered 2nd Task");
    Thread.Sleep(2000);
    Console.WriteLine(t.Result);
});

tk1.Wait();

and below is the same done with dataflow

var df1 = new TransformBlock<int,int>(t =>
{
    Console.WriteLine("Entered 1st DF");
    Thread.Sleep(3000);
    return 2;
});

var df2 = new ActionBlock<int>(t =>
{

    Console.WriteLine("Entered 2nd Task");
    Thread.Sleep(2000);
    Console.WriteLine(t);
});

df1.LinkTo(df2);

df1.Completion.ContinueWith(t =>
df2.Complete());

df1.Post(2);

df2.Completion.Wait();

Task.ContinueWith looks simple than the lengthy syntax which dataflow provides. Can anyone please clarify the difference between the two.

Data flow i used to create a compleax proccesing pipleins, where the flow can branch and merge and loop. ( The example you are showing here is to simple)

Task.ContinueWith is used in a simpler code when the flow in just a list of function done one after another.

With your code, there's actually no difference.

But you're doing it wrong for data flow - what's the use of a transform block, that only always ever produces one result independent of input?

Better do some processing...

var df1 = new TransformBlock<int,int>(input =>
    {
        Console.WriteLine("Entered 1st DF");
        Thread.Sleep(3000);
        return input+1;
    });

... and then you see the difference:

Task.Run will just run once, but

df1.Post(2);
df1.Post(5);
df1.Post(27);
df1.Post(-1);

will all run through your data flow mesh and produce output.

And BTW: using async / await instead of Task.ContinueWith can make your code a lot simpler and more readable.

You need to fully understand the basics for TPL Dataflow , as right now you trying to do things that can easily be done by TPL Dataflow pipeline itself:

df1.LinkTo(df2, new DataflowLinkOptions { PropagateCompletion = true });

Now you don't need to use ContinueWith for a df1.Completion , but you still need to notify the df1 block (ugly naming, by the way) to (surprise) complete , as it doesn't know when to finish, comparing with task:

df1.Post(2);
df1.Complete();

Calling this method will deny all other messages sent to df1 block, and after it's buffer became empty, it will propagate the completion down the pipeline, so you simply need to wait for it (either synchronously or asynchronously):

df2.Completion.Wait();
// or
await df2.Completion;

So, basically, the difference is that task can be run only once, comparing with block, which runs forever until you manually complete it. Note that you still can continue the Completion task for a block:

df2.Completion.ContinueWith(t =>
{
    // some other logic here
});

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM