Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.wait and continueWIth

I am having a task like below.

var task = Task<string>.Factory.StartNew(() => longrunningmethod()
    .ContinueWith(a =>
             longrunningmethodcompleted((Task<string>)a,
                  TaskScheduler.FromCurrentSynchronizationContext())));

task.Wait();

My task will call the longrunningmethod and after completing it will call completed method. Inside my longrunningmethod I am delaying by Thread.Sleep(30000). When I use Task.wait system hangs and it's not calling longrunningmethodcompleted method. If I don't use Task.wait everything flows good.

like image 746
user2107843 Avatar asked Jul 05 '13 13:07

user2107843


1 Answers

I strongly suspect your context is a UI context.

In that case, you're causing the deadlock because you're telling longrunningmethodcompleted to execute on the current SynchronizationContext.

Then you're blocking that context by calling Wait. The continuation will never complete because it needs to execute on the thread that is blocked in Wait.

To fix this, you can't use Wait on a continuation running in that context. I'm assuming that longrunningmethodcompleted must run on the UI thread, so the solution is to replace the call to Wait with a call to ContinueWith:

var ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task<string>.Factory.StartNew(() => longrunningmethod()
    .ContinueWith(a =>
         longrunningmethodcompleted((Task<string>)a,
         ui);
task.ContinueWith(..., ui);

Or, you can upgrade to VS2012 and use async/await, which lets you write much cleaner code like this:

var task = Task.Run(() => longrunningmethod());
await task;
longrunningmethodcompleted(task);
like image 112
Stephen Cleary Avatar answered Oct 21 '22 11:10

Stephen Cleary