Task.Factory.StartNew is dangerous. It uses TaskScheduler.Current
as opposed to TaskScheduler.Default
.
In your case OnFinishWorkEventHandler
is fired from ContinueWith
which is running in UI thread by TaskScheduler.FromCurrentSynchronizationContext()
. So at that point TaskScheduler.Current
is UIScheduler and not TaskScheduler.Default
(threadpool scheduler).
That's why your second task is scheduled in UI Thread which causes UI to freeze.
To fix this use Task.Run
which always points to TaskScheduler.Default
. Task.Run
is new in .net 4.5, if you're in .net 4.0 you can create your TaskFactory
with default parameters and you can use that.
private static readonly TaskFactory factory = new TaskFactory(CancellationToken.None,
TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
Then use
factory.StartNew(...);
If you're just going to use it only once you don't need to create a factory instance yourself, just specifying TaskScheduler
explicitly will be fine.
Task.Factory.StartNew(() =>{
//Your code here
}, _tokenSource.Token,
TaskCreationOptions.None,
TaskScheduler.Default)//Note TaskScheduler.Default here
.ContinueWith(
t =>
{
//finish...
if (OnFinishWorkEventHandler != null)
OnFinishWorkEventHandler(this, EventArgs.Empty);
}
, TaskScheduler.FromCurrentSynchronizationContext());