「C Sharpの基礎 - マルチスレッドとGUI」の版間の差分

ナビゲーションに移動 検索に移動
37行目: 37行目:


== Invokeメソッドを使う ==
== Invokeメソッドを使う ==
Windows フォームアプリケーションの場合、GUIコントロールのInvokeメソッドを呼び出すと、<br>
コントロールの<code>Invoke</code>メソッドを使用する場合、呼び出し元のオブジェクトのスレッドにおいてデリゲートを実行することができる。<br>
呼び出し元のオブジェクトのスレッドにおいてデリゲートを実行することができる。<br>
実行結果は、前項とほぼ同じなので省略する。<br>
  <syntaxhighlight lang="cpp">
  <syntaxhighlight lang="cpp">
  private async void buttonl_Click(object sender, RoutedEventArgs e)
  private async void buttonl_Click(object sender, RoutedEventArgs e)
54行目: 52行目:
       }));
       }));
     });
     });
}
</syntaxhighlight>
<br>
また、コントロールの<code>Invoke</code>メソッドと<code>InvokeRequired</code>プロパティを組み合わせて使用することもできる。<br>
* <code>Invoke</code>メソッド
*: 指定された処理をそのコントロールが生成されたスレッドで実行する。
*: 多少オーバーヘッドが発生する。
* <code>InvokeRequired</code>プロパティ
*: コントロールにアクセスする時、<code>Invoke</code>メソッドを使用する必要があるかどうかを判断する。
<syntaxhighlight lang="c#">
// 必要に応じてInvokeするコード
public partial class Form1 : Form
{
    // ...略
    private async void buttonl_Click(object sender, RoutedEventArgs e)
    {
      InvokeIfRequired(button1, () => button1.Enabled = false);
      InvokeIfRequired(button1, () => button1.Enabled = true);
    }
    private void InvokeIfRequired(Control control, Action action)
    {
      if (control.InvokeRequired)
      {
          control.Invoke(action, new object[] { });
      }
      else
      {
          action();
      }
    }
}
</syntaxhighlight>
<br>
また、以下のようなコントロールに対する拡張メソッドとして定義することにより、簡潔に記述できるようになる。<br>
<syntaxhighlight lang="c#">
public partial class Form1 : Form
{
    // ...略
    private async void buttonl_Click(object sender, RoutedEventArgs e)
    {
      button1.InvokeIfRequired(() => button1.Enabled = false);
      button1.InvokeIfRequired(() => button1.Enabled = true);
    }
    // ...略
}
// コントロールに対する拡張メソッド
public static class ControlExtensions
{
    // 戻り値が不要な場合
    public static void InvokeIfRequired(this Control control, Action action)
    {
      if (control.InvokeRequired)
      {
          control.Invoke(action, new object[] { });
      }
      else
      {
          action();
      }
    }
    // 戻り値が必要な場合
    public static T InvokeIfRequired<T>(this Control control, Func<T> func)
    {
      if (control.InvokeRequired)
      {
          return (T)control.Invoke(func, new object[] { });
      }
      else
      {
          return func();
      }
    }
  }
  }
  </syntaxhighlight>
  </syntaxhighlight>

案内メニュー