Bug 5659 - Task.WaitAll Doesn't Execute Immediately And Doesn't Honor Timeout
Summary: Task.WaitAll Doesn't Execute Immediately And Doesn't Honor Timeout
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 5.2
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2012-06-14 15:50 UTC by Ryan Alford
Modified: 2012-06-18 12:25 UTC (History)
2 users (show)

Is this bug a regression?: ---
Last known good build:

Replication Code (1.32 MB, application/zip)
2012-06-18 09:28 UTC, Ryan Alford

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Ryan Alford 2012-06-14 15:50:53 UTC
I've run across a possible bug with Task.WaitAll.

The Task.WaitAll(Task[]) method does not execute the tasks at all.  None of the tasks will run, so the application just sits there.  I've set breakpoints in the methods that the task would run, and the breakpoints never get hit.

The Task.WaitAll(Task[], int) overload seems to use the timeout parameter as a "wait this amount of time before starting the tasks".  If I put '10000' as the timeout, it takes 10 seconds before the tasks START(breakpoints get hit after 10 seconds).  If I put '0' as the timeout, the tasks start immediately.
Comment 1 Ryan Alford 2012-06-14 15:55:19 UTC
MonoTouch version is 5.2.12.
Comment 2 Sebastien Pouliot 2012-06-15 21:11:31 UTC
c.c. Jeremie
Comment 3 Jérémie Laval 2012-06-18 06:29:32 UTC
Hey Ryan,

Could you try the latest MonoTouch release (version 5.3.4 in the alpha channel)? A number of fixes for that part went into that release

Comment 4 Ryan Alford 2012-06-18 07:37:26 UTC
Sure.  How do I get to the alpha channel?  Also, how will I be able to go back to the 5.2.12 release?  Uninstall 5.3 and reinstall 5.2?
Comment 5 Jérémie Laval 2012-06-18 08:17:48 UTC
Yes. Go to MonoDevelop > Check For Update and in the upper-left corner you can change the update channel you are registered to. Choose 'Alpha' and install the MonoDevelop/MonoTouch version that gives you. You should then be able to roll back by selecting Stable again from the same dropdown.
Comment 6 Ryan Alford 2012-06-18 08:30:23 UTC
Just tried on MonoTouch 5.3.4, and I am still seeing the same issue.
Comment 7 Jérémie Laval 2012-06-18 09:00:59 UTC
Could you attach a code reproduction of the problem?
Comment 8 Ryan Alford 2012-06-18 09:28:30 UTC
Created attachment 2077 [details]
Replication Code
Comment 9 Jérémie Laval 2012-06-18 09:57:09 UTC
Thanks, the problem seems to stem from the MonoTouch synchronization context scheduler.

If you remove the scheduler from the ContinueWith call in the controller it works fine. As a workaround, wrap the ContinueWith body in a InvokeOnMainThread(delegate {}) which will give you the same behavior.

In the meantime I will investigate what the problem is.
Comment 10 Jérémie Laval 2012-06-18 12:25:09 UTC

I just realized what went wrong. It's not a bug per se but a tricky behavior of how the TPL works.

When you schedule any type of task, it will by default run on the current scheduler which is basically the last scheduler that was used on the current thread.

In your case, you setup the initial continuation in a MonoTouch scheduler which proxy everything to the main loop which mean your continuation is running on the main thread. The problem is that the two tasks you are then creating inherit that MonoTouch scheduler too and thus both get also scheduled on the main loop. As you probably guessed, the WaitAll call will then effectively make you deadlock because you never return to the main loop to execute these two tasks you just scheduled.

Incidentally your code probably doesn't do what you intended so when creating your task in nested context you should pass TaskScheduler.Default to StartNew to ensure it's correctly run on the general purpose scheduler and not on a default inherited one.