Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continue Task after all tasks finish

In some class I want to load 2 collection asynchronously with Task and stop busyindicator

I try Something like this

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
WaitingIndicatorViewModel.IsBusy = true;
var loadData1 = new Task<ObservableCollection<Data1>>(GetData1FromService).ContinueWith(t => Data1Collection = t.Result, uiScheduler);
var loadData2 = new Task<ObservableCollection<Data2>>(GetData2FromService).ContinueWith(t => Data2Collection = t.Result, uiScheduler);

Task.Factory.StartNew(() =>{
                loadData1.Start();//<--Exception here           
                loadData2.Start();
                Task.WaitAll(loadData1, loadData2);
        })
.ContinueWith(o => WaitingIndicatorViewModel.IsBusy = false, uiScheduler);

But this throw an exception InvalidOperationException:Start may not be called on a continuation task.

Why this doesn't work, and how can I run continue task after finishing both tasks, without blocking current thread?

like image 333
Arsen Mkrtchyan Avatar asked Jan 14 '12 19:01

Arsen Mkrtchyan


People also ask

What is a continuation task?

A continuation task (also known just as a continuation) is an asynchronous task that's invoked by another task, known as the antecedent, when the antecedent finishes.

Does task WhenAll start the tasks?

WhenAll starts both Tasks at the same time and executes them in parallel, the outcome is that instead of taking 3 seconds to run the program it just takes 2 seconds, that's a huge performance enhancement! At this point you guys might be thinking: “Okay, this is nice and I can see how better it is to use Task.

What is task when all?

WhenAll(IEnumerable<Task>) Creates a task that will complete when all of the Task objects in an enumerable collection have completed.


1 Answers

Instead of:

var loadData1 = new Task<ObservableCollection<Data1>>(GetData1FromService)
               .ContinueWith(t => Data1Collection = t.Result, uiScheduler);

I think what you mean is:

var loadData1 = new Task<ObservableCollection<Data1>>(GetData1FromService);
loadData1.ContinueWith(t => Data1Collection = t.Result, uiScheduler);

Now you can (later) call:

loadData1.Start();

The difference is that we are assigning loadData1 to the outermost task. In your original code, you are assigning loadData1 the result of ContinueWith, which is something else (a second task, so that you can wait or continue from the second task).

Note: if you want to wait for the inner task, you should capture the result of the ContinueWith call into a new variable, and wait on that.

like image 176
Marc Gravell Avatar answered Sep 29 '22 03:09

Marc Gravell