C# の async/await を利用した非同期処理はお手軽で良いけれど、XPSDocument なんかをいじってると、Task.Run()
で返される Task オブジェクトが MTA なため時々実行できませんと怒られてしまう。そういう場合、STA で実行される Task オブジェクトを生成してやると回避できる場合がある。
そこで見よう見まねで、Task.Run()
ぽい感じで使える、STA で実行されるスレッドを生成する Task オブジェクトを返すクラス STATask を書いてみた。
statask.cs
// STAで実行されるTaskオブジェクトを生成する
class STATask
{
public static Task Run<T>(Func<T> func)
{
var tcs = new TaskCompletionSource<T>();
var thread = new Thread(() =>
{
try
{
tcs.SetResult(func());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
public static Task Run(Action act)
{
return Run(() =>
{
act();
return true;
});
}
}
以下のような感じで使うことができる。
sample.cs
private async void foo()
{
await STATask.Run(() =>
{
// 非同期実行したい処理
Thread.Sleep(1000);
});
}