8

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.

1
  • Sounds like a deadlock to me, are you doing this in a single threaded environment? I've seen this happen in Windows Phone development before. (related) Commented Jul 5, 2013 at 13:46

3 Answers 3

14

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); 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks all.Stephen Yes it works.I am using vs2010 unfortunately can't upgrade now to vs2012.IS there a way I can make the UI thread to wait until task and continue with completes.
Your only options are either to run continuations without the task scheduler, or to put the remainder of your work as a continuation. Yes, this gets incredibly messy very quickly for any kind of real-world asynchronous scenario. And this is why async was invented.
0

Well it is hard to tell what is wrong with your code without seeing what the actual asynch actions are, all I know is according to MSDN waits for the task to be completed. Is it possible that because you are trying to use the current SynchronizationContext your actions blocks?

The reason I am asking is because you

  1. Start the task
  2. Wait for the task to complete (which is the continue with task)
  3. Task tries to continue with current SynchronizationContext
  4. Task tries to acquire the main thread
  5. Task scheduled to take the thread after the Wait is completed
  6. But Wait is waiting on current Task to complete (deadlock)



What I mean is that the reason your program works with Thread.Sleep(seconds) is because after the time limit is up the thread will continue.

1 Comment

Charles thanks Yes I understand now that deadlock happened The reason I need Task.wait after continue with is to make the UI thread wait.is there a way i can use the main thread wait until task and continue completes.
-1

Thread.Sleep(nnn) is blocking. Use Task.Delay(nnn) and await:

await Task.Delay(30000); 

Edited to add: Just noted the tag says C# 4. This requires C# 5 and the new async await support. Seriously, if you're doing async and tasks, you need to upgrade.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.