{"id":983,"date":"2010-10-15T10:59:00","date_gmt":"2010-10-15T10:59:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2010\/10\/15\/faq-startnew-with-taskscheduler-fromcurrentsynchronizationcontext-doesnt-work\/"},"modified":"2010-10-15T10:59:00","modified_gmt":"2010-10-15T10:59:00","slug":"faq-startnew-with-taskscheduler-fromcurrentsynchronizationcontext-doesnt-work","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/faq-startnew-with-taskscheduler-fromcurrentsynchronizationcontext-doesnt-work\/","title":{"rendered":"FAQ :: StartNew() with TaskScheduler.FromCurrentSynchronizationContext() doesn\u2019t work?"},"content":{"rendered":"<p class=\"MsoNormal\">We&rsquo;ve seen a number of folks write the following code to execute\non the UI thread and get unexpected behavior.<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: 'courier new', courier\">TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();<\/p>\n<p>Task uiTask = Task.Factory.StartNew(delegate<br>{<br>&nbsp;&nbsp; &nbsp;\/\/ &hellip; Update UI component; BUG!<br>}, uiScheduler);<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: 'courier new', courier\"><br><\/span><\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">The issue is that the StartNew call will bind to the\nfollowing overload&hellip;<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\"><span style=\"font-family: 'courier new', courier\">public Task\nStartNew(Action&lt;Object&gt;\naction, Object state);<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: 'courier new', courier\"><br><\/span><\/p>\n<p class=\"MsoNormal\">&hellip;because the following overload does not exist!<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\"><s><span style=\"font-family: 'courier new', courier\">public<\/span><\/s><s><span style=\"font-family: 'courier new', courier\"> Task StartNew(Action\naction, TaskScheduler scheduler);<\/span><\/s><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: 'courier new', courier\"><br><\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<p>As a result, uiScheduler just becomes the AsyncState for\nuiTask instead of being the TaskScheduler on which it executes, so the UI\nupdates will end up running on the ambient scheduler captured during the\nStartNew call (usually not desired).&nbsp;\nOnce the issue is identified, it&rsquo;s easy to pick the right overload:<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\"><span style=\"font-family: 'courier new', courier\">Task t = Task.Factory.StartNew(delegate<br>{<br>&nbsp;&nbsp; &nbsp;\/\/ &hellip; Update UI component<br><span style=\"font-family: Arial, Helvetica, sans-serif\"><span style=\"font-family: 'courier new', courier\">}, CancellationToken.None,\nTaskCreationOptions.None, uiSched<\/span>uler);<\/span><\/span><\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">Note that you won&rsquo;t run into the same confusion with\nContinueWith (the API that&rsquo;s more commonly used with TaskScheduler.FromCurrentSynchronizationContext),\nbecause we do have overloads of ContinueWith that take just TaskScheduler.<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">So why didn&rsquo;t we add overloads of StartNew that take just\nTaskScheduler?&nbsp; The short answer is that\nwe were trying to reduce the number of overloads and didn&rsquo;t expect this\nparticular issue to be problematic.&nbsp; It&rsquo;s\nsomething we&rsquo;d love to address, but unfortunately, adding the new overloads now\ncould potentially break existing code that actually wanted to pass a TaskScheduler\nas the AsyncState.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&rsquo;ve seen a number of folks write the following code to execute on the UI thread and get unexpected behavior. &nbsp; TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task uiTask = Task.Factory.StartNew(delegate{&nbsp;&nbsp; &nbsp;\/\/ &hellip; Update UI component; BUG!}, uiScheduler); The issue is that the StartNew call will bind to the following overload&hellip; &nbsp; public Task StartNew(Action&lt;Object&gt; action, Object [&hellip;]<\/p>\n","protected":false},"author":485,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[7907,7923,7909,7912],"class_list":["post-983","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4","tag-faq","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>We&rsquo;ve seen a number of folks write the following code to execute on the UI thread and get unexpected behavior. &nbsp; TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task uiTask = Task.Factory.StartNew(delegate{&nbsp;&nbsp; &nbsp;\/\/ &hellip; Update UI component; BUG!}, uiScheduler); The issue is that the StartNew call will bind to the following overload&hellip; &nbsp; public Task StartNew(Action&lt;Object&gt; action, Object [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/983","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/485"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=983"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/983\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=983"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=983"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}