Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to marshall work onto the main thread using TPL tasks in C# without causing a deadlock?
    primarykey
    data
    text
    <p>I am writing a library that is consuming a resource and for whatever reason the API was designed in a way that events will be raised on different threads but calls of the API has to be done on the main thread.</p> <p>Let's say the API that I am trying to consume is defined as (I am going to omit event definitions):</p> <pre class="lang-cs prettyprint-override"><code>public sealed class DodgyService { public void MethodThatHasToBeCalledOnTheMainThread() { ... } } </code></pre> <p>To consume this API I have added a service on my library called Service (Yup, very original name) that will create a new task (that will run on the main thread as I am specifying a TaskScheduler that has been created from the <code>SynchronizationContext</code>).</p> <p>Here is my implementation:</p> <pre class="lang-cs prettyprint-override"><code>public class Service { private readonly TaskFactory _taskFactory; private readonly TaskScheduler _mainThreadScheduler; public Service(TaskFactory taskFactory, TaskScheduler mainThreadScheduler) { _taskFactory = taskFactory; _mainThreadScheduler = mainThreadScheduler; } // Assume this method can be called from any thread. // In this sample is called by the main thread but most of the time // the caller will be running on a background thread. public Task ExecuteAsync(string taskName) { return _taskFactory.StartNew( () =&gt; ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(taskName), new CancellationToken(false), TaskCreationOptions.None, _mainThreadScheduler) .ContinueWith(task =&gt; Trace.TraceInformation("ExecuteAsync has completed on \"{0}\"...", taskName)); } private void ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(string taskName) { Trace.TraceInformation("Starting \"{0}\" really long call...", taskName); new DodgyService().MethodThatHasToBeCalledOnTheMainThread(); Trace.TraceInformation("Finished \"{0}\" really long call...", taskName); } </code></pre> <p>}</p> <p>Now, if I perform the call of my service (on the main thread) and try to wait on the main thread the application enters a deadlock as the main thread will be waiting for the tasks that has been scheduled to execute on the main thread.</p> <p>How do I marshall these calls onto the main thread without blocking the entire process?</p> <p>At some point I thought on performing the detection of the main thread before creating the new task but I don't want to hack this.</p> <p>For anybody interested, I got a gist <a href="https://gist.github.com/rodrigoelp/7409042" rel="nofollow noreferrer">here</a> with the code and a WPF app that exhibits the issue.</p> <p><strong><em>On btw, the library has to be written on .net framework 4.0</em></strong></p> <p>Edit! I solved my issue following the advice provided by <a href="https://stackoverflow.com/users/80274/scott-chamberlain">Scott Chamberlain</a> as provided <a href="https://stackoverflow.com/questions/4269800/webbrowser-control-in-a-new-thread/4271581#4271581">here</a> </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload