3

このリンクのコード: http://c-sharp-programming.blogspot.com/2008/07/cross-thread-operation-not-valid.htmlでは、デリゲートを使用してワーカーからテキスト ボックスの値を更新します。スレッド。

私は基本的に何が起こっているかを見ることができますが、具体的にはこの行の構文は次のとおりです。

label1.Invoke(del, new object[] { newText });

は私を混乱させます。誰か説明してくれませんか?パラメータが 1 つしかないのに、デリゲートに新しいオブジェクト配列構文を使用するのはなぜですか?

完全なコード:

delegate void updateLabelTextDelegate(string newText);
private void updateLabelText(string newText)
{
 if (label1.InvokeRequired)
 {
     // this is worker thread
     updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
     label1.Invoke(del, new object[] { newText });
 }
 else
 {
     // this is UI thread
     label1.Text = newText;
 }
}
4

4 に答える 4

4

TL;DR:

Control.InvokeデリゲートでDynamicInvokeを呼び出しています。これは、パラメーターのオブジェクト配列を使用して、任意のデリゲート タイプを操作します。

///

C#のキーワードdelegateは、関数ポインターの型を指定するのと似ています。その型を使用して、特定の署名のメソッドを渡すことができます。あなたの例では、署名は1つの引数(文字列)を取り、何も返さない(void)メソッド用です。メソッドupdateLabelTextはその sig と一致します。この線:

updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);

全文の言い方は次のとおりです。

updateLabelTextDelegate del = updateLabelText;

次に、メソッドへのdelポインターである変数をメソッドに渡すことができます。updateLabelTextControl.Invoke

label1.Invoke(del, new object[] { newText });

params署名で使用されているおかげでControl.Invoke、明示的に言う必要さえありませんobject[]

label1.Invoke(del, newText);

Invokeオブジェクトの配列を受け取り、指定されたデリゲートへの引数として使用します。(はい、更新メソッドは1つの文字列引数を取ります。読み続けてください)変数を使用して、自分自身を呼び出すdelことができupdateLabelTextます:

del(newText);

これは本質的に次と同じです。

updateLabelText(newText);

内部Control.Invokeでは、メソッドを呼び出していますが、デリゲートのいくつかのヘルパー メソッドのおかげで、必要な引数の数を知るdel必要はありません次のようなものが見つかります。

編集私は科学のためにいくつかの深い掘り下げを行いました.呼び出しは内部的に次のようになります:

del.DynamicInvoke(args);

はどこargsにありますかobject[]。デリゲート変数 (Delegate 型) でできることの詳細については、こちらを参照してください。

于 2012-04-20T20:44:35.413 に答える
3

Control.Invokeのメソッド シグネチャを見ると、 がかかることがわかりますparams Object[] argsobject[] argsまたは単一の引数を渡すことができます。

于 2012-04-20T20:47:27.500 に答える
2

Invokeオブジェクト配列はデリゲートのメソッドに渡されます。この場合updateLabelTextDelegate、単一のパラメーターを取るstringため、配列内の単一の要素になります。

実際、配列を明示的に作成する必要はありません。

label1.Invoke(del, newText)

も有効です。

于 2012-04-20T20:46:07.030 に答える
1

Invokeまず、これはデリゲートを呼び出しているのではなくInvokeコントロールを呼び出していることに注意してください。Control.Invokeここで使用されて いる署名を見ると、次のようになります。

public Object Invoke(
    Delegate method,
    params Object[] args
)

メソッドが1 つの特定のデリゲート型を受け取る場合、そのデリゲートに適切なパラメーター型を受け取ることができます。あなたの場合、デリゲートは1 つのパラメーターしか取りAction<string, string, int>ませんが、上記の非常に一般的なアプローチを使用して、次のパラメーターを渡したいとします。

control.Invoke(someDelegate, new object[] { "foo", "bar", 10 });

object[]したがって、デリゲート型も一般的なままであるため、一般性を提供するために が存在するというのが答えです。これは少し似てMethodInfo.Invokeいます - コンパイル時にパラメーターがいくつあるかを知らなくても、型の値はobject[]さまざまな状況を可能にする最良の方法です。

于 2012-04-20T20:46:57.100 に答える