Skip to content

Instantly share code, notes, and snippets.

@rodrigoelp
Last active December 27, 2015 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rodrigoelp/7409042 to your computer and use it in GitHub Desktop.
Save rodrigoelp/7409042 to your computer and use it in GitHub Desktop.
Task on main thread sample. How to marshall work onto the main thread without causing deadlocks?
using System;
using System.Threading.Tasks;
namespace TPLSample
{
public partial class MainWindow
{
private readonly TaskFactory _taskFactory = new TaskFactory();
private readonly Service _service;
public MainWindow()
{
InitializeComponent();
_service = new Service(_taskFactory, TaskScheduler.FromCurrentSynchronizationContext());
Closed += HandleClosed;
}
private void HandleClosed(object sender, EventArgs e)
{
// Please assume this event is raised on a thread other than the main thread.
var list = new[]
{
_service.ExecuteAsync("first task"),
_service.ExecuteAsync("second task"),
_service.ExecuteAsync("third task")
};
//uncommenting this line blocks all three previous activities as expected
//as it drives the current main thread to wait for other tasks waiting to be executed by the main thread.
//Task.WaitAll(list);
}
}
}
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Org.Company.Product;
namespace TPLSample
{
public class Service
{
private readonly TaskFactory _taskFactory;
private readonly TaskScheduler _mainThreadScheduler;
public Service(TaskFactory taskFactory, TaskScheduler mainThreadScheduler)
{
_taskFactory = taskFactory;
_mainThreadScheduler = mainThreadScheduler;
}
public Task ExecuteAsync(string taskName)
{
return _taskFactory.StartNew(
() => ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(taskName),
new CancellationToken(false), TaskCreationOptions.None, _mainThreadScheduler)
.ContinueWith(task => 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);
}
}
}
using System.Diagnostics;
using System.Threading;
namespace Org.Company.Product
{
public sealed class DodgyService
{
public void MethodThatHasToBeCalledOnTheMainThread()
{
Trace.TraceInformation("Hello! I am going to sit here for a while...");
Thread.Sleep(1500);
Trace.TraceInformation("... woah! sorry! I forgot you were there! I am back!");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment