C#

STAで実行されるTaskの生成

More than 3 years have passed since last update.

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);
  });
}