2012-04-20 10 views
3

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

私は基本的に何が起こっているか見ますが、特にこの行の構文ができます。

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; 
} 
} 
+0

間違いですが、label1.Invoke()はデリゲートではありません。 'label1.Invoke(del、newText);と書いてください。 –

+0

彼はlabel1.Invoke()がデリゲートだと言っていましたか?私はそれを読まなかった。また、paramsのおかげで、明示的なオブジェクトなしで単一のparamを使用することができます。 – payo

答えて

4

TL; DR:

Control.Invokeは、任意のデリゲート型で動作するようにパラメータのオブジェクト配列を受け取り、あなたのデリゲートにDynamicInvokeを呼びかけています。

//

キーワードanalagousにC#でdelegate関数ポインタのタイプを指定します。そのタイプを使用して、特定の署名のメソッドを渡すことができます。あなたの例では、シグネチャは1 arg(文字列)をとり、何も返しません(void)メソッドのためのものです。メソッドupdateLabelTextはそのsigと一致します。ライン:

updateLabelTextDelegate del = updateLabelText; 

次に、あなたが今Control.Invoke方法に方法updateLabelTextへのポインタである、あなたの変数delを渡すことができます。

updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText); 

だけ言ってのフルテキストの方法です。

paramsControl.Invoke署名に使用されているおかげで、あなたも明示的に Invokeは、それが使用しますオブジェクトの配列を、取る object[]

label1.Invoke(del, newText); 

だと言う必要はありません

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

与えられた代表団への議論として。

基本的に同じだろう
del(newText); 

Control.Invokeインサイド
updateLabelText(newText); 

あなたの変数delで(はい、あなたの更新方法は、読書を維持し、1つの文字列の引数を取ります)、あなたコールupdateLabelText自分ができました彼らはあなたのdelメソッドを呼び出していますが、にはがありません。代理人のいくつかのヘルパーメソッドのおかげで、いくつの引数が必要なのか知ることができます。

EDIT私はいくつかの深い科学のために掘り、invocationが内部でより多くのように:あなたはこのような何かを見つけるだろうargsobject[]ある

del.DynamicInvoke(args); 

。デリゲート変数(デリゲートタイプ)でできることの詳細については、hereをお読みください。

+0

詳細な回答ありがとうございました。 :) –

2

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

実際には、アレイは、明示的に作成する必要はありません、と

label1.Invoke(del, newText) 

も有効です。

+0

+1は 'new object []'を使用していないためですが、これは 'params'のおかげで唯一のオプションです – payo

1

まず、デリゲートでInvokeを呼び出していないことに注目してください。Invokeコントロールを呼び出しています。あなたがここで使用されているControl.Invokeの署名を見れば今、それはこのです:

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

の方法は1特定デリゲート型を取った場合、それはそのデリゲートのための適切なパラメータの型を取ることができます。

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

だから、答えはobject[]があるということである: - デリゲートはパラメータを1つだけ取りますが、私たちはAction<string, string, int>に渡したいとしあなた場合には上記の非常に一般的なアプローチを使用して、我々はしていることを行うことができますデリゲートのタイプも一般的なままであるため、一般性を提供するためにそこにあります。 MethodInfo.Invokeのようなものです - コンパイル時に何個のパラメータがあるか分からずに、タイプobject[]の値はさまざまな状況を可能にする最良の方法です。

3

Control.Invokeのメソッドシグネチャを見ると、params Object[] argsが表示されます。 object[] argsまたは1つの引数を渡すことができます。

関連する問題