MTAThread設定時に、OpenFileDialog()を呼び出すとエラーになる対処法

C#

現象

MTAThread設定時に、OpenFileDialogを実行すると下記エラーが発生する。
System.Threading.ThreadStateException’OLE が呼び出される前に、現在のスレッドが Single Thread Apartment (STA) モードに設定されていなければなりません。Main 関数に STAThreadAttribute が設定されていることを確認してください。 この例外はデバッガーがプロセスにアタッチされている場合にのみ発生します。

エラーが発生するコード

static class Program
{
  /// アプリケーションのメイン エントリ ポイントです。
  [MTAThread]
  static void Main()
  {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
  }
}
 private void Button1_Click(object sender, EventArgs e)
 {
   OpenFileDialog ofd = new OpenFileDialog();
   if (ofd.ShowDialog() == DialogResult.OK)
   {
   //省略
   }
 }

原因

OLE が呼び出される前に、現在のスレッドが Single Thread Apartment (STA) モードに設定されていないと発生する。

対策

対策済みコード

private void Button2_Click(object sender, EventArgs e)
{
  OpenFileDialog frm = new OpenFileDialog();
  DialogResult ret = STAShowDialog(frm);
  if (ret == DialogResult.OK)
  {
  //省略
  }
}
///
private DialogResult STAShowDialog(OpenFileDialog dialog)
{
  DialogState state = new DialogState();
  state.dialog = dialog;
  System.Threading.Thread t = new System.Threading.Thread(state.ThreadProcShowDialog);
  t.SetApartmentState(System.Threading.ApartmentState.STA);
  t.Start();
  t.Join();
  return state.result;
}
/// <summary>
/// バックグラウンドスレッドでFileDialog.ShowDialogを呼び出すために状態と戻り値を保持するクラス
/// </summary>
public class DialogState
{
  public DialogResult result;
  public OpenFileDialog dialog;
  public void ThreadProcShowDialog()
  {
    result = dialog.ShowDialog();
  }
}

参考サイト

コメント