Continue Task after all tasks finish

2019-03-30 01:21发布

问题:

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?

回答1:

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.