How to create a task (TPL) running a STA thread?

Using Thread is pretty straightforward

 Thread thread = new Thread(MethodWhichRequiresSTA);
thread.SetApartmentState(ApartmentState.STA);

How to accomplish the same using Tasks in a WPF application? Here is some code:

Task.Factory.StartNew
(
() =>
{return "some Text";}
)
.ContinueWith(r => AddControlsToGrid(r.Result));

I'm getting an InvalidOperationException with

The calling thread must be STA, because many UI components require this.

65015 次浏览

You can use the TaskScheduler.FromCurrentSynchronizationContext Method to get a TaskScheduler for the current synchronization context (which is the WPF dispatcher when you're running a WPF application).

Then use the ContinueWith overload that accepts a TaskScheduler:

var scheduler = TaskScheduler.FromCurrentSynchronizationContext();


Task.Factory.StartNew(...)
.ContinueWith(r => AddControlsToGrid(r.Result), scheduler);

Dispatcher.Invoke could be a solution. e.g.

    private async Task<bool> MyActionAsync()
{
// await for something, then return true or false
}
private void StaContinuation(Task<bool> t)
{
myCheckBox.IsChecked = t.Result;
}
private void MyCaller()
{
MyActionAsync().ContinueWith((t) => Dispatcher.Invoke(() => StaContinuation(t)));
}