What is InvokeRequired?
delegate void SetTextCallback(Control ctl, String str);// 設置textbox.text
delegate string GetTextCallback(Control ctl); //讀取textbox.text
public string gettext(Control ctl)
{
if (this.InvokeRequired) //InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true.
{
GetTextCallback d = new GetTextCallback(gettext);
string x;
x = (string)this.Invoke(d, new Object[] { ctl });
return x;
}
else
{
return ctl.Text;
}
}
public void SetText(Control ctl, String str)
{
if (this.InvokeRequired)
{
SetTextCallback s = new SetTextCallback(SetText);
this.Invoke(s, ctl, str);
}
else
{
ctl.Text = str;
}
}
from https://so-zou.jp/software/tech/programming/c-sharp/thread/thread-safe-call.htm
独自の実装
コントロールをスレッド セーフとするには、次のように呼び出します。
- コントロールが破棄されていないか、IsDisposedプロパティで確認する。
- コントロールのInvokeRequiredプロパティから、スレッドが異なるか確認する。
- コントロールと同一のスレッドで実行されるように処理する。
- スレッドが異なる … コントロールと同一のスレッドで実行されるように、delegateを使用してInvoke()メソッドから呼び出す。
- スレッドが同一 … コントロールを直接呼び出す。
破棄されているコントロールへアクセスすると、ObjectDisposedException例外が発生します。
スレッドを考慮をせずコントロールにアクセスすると、「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'control' がアクセスされました。」としてInvalidOperationException例外が発生します。
コントロールのスレッドでの実行
public object Invoke(
Delegate method
)
Control.Invoke メソッド (Delegate) (System.Windows.Forms) | MSDN
デリゲートを非同期で実行するならば、BeginInvoke()で呼び出します。
public IAsyncResult BeginInvoke(
Delegate method
)
Control.BeginInvoke メソッド (Delegate) (System.Windows.Forms) | MSDNサンプルコード
// Windowsフォームコントロールに対して非同期な呼び出しを行うためのデリゲート
delegate void SetTextCallback( TextBox textBox, string text );
private void SetText( TextBox textBox, string text ) { // コントロールが破棄されているならば、何もしない if (textBox.IsDisposed) return; // 呼び出し元のコントロールのスレッドと異なるかを確認する if( textBox.InvokeRequired ) { // このブロックは、別スレッドで実行される // 同一メソッドへのコールバックを作成する SetTextCallback delegateMethod = new SetTextCallback( SetText ); // コントロールの親のInvoke()メソッドを呼び出すことで、 // 呼び出し元のコントロールのスレッドでこのメソッドを実行する this.Invoke( delegateMethod, new object[] { textBox, text } ); } else { // このブロックは、同一スレッドで実行される // コントロールを直接呼び出す textBox.Text = text; } }
留言
張貼留言