2009-07-31 8 views
0

をスローし、多分私はのFuncの使い方を誤解しますが、私のWorkerthreadからgetCurrentValue(cb_message_type)を呼び出すときC#のFuncデリゲートだからスレッド例外

Func<ComboBox, string> getCurrentValue = s => s.SelectedValue.ToString(); 

は、スレッドのエラーを作成します。 ComboboxのSelected Valueを取得する最良の解決策は何ですか?

多くのおかげで、
rAyt

編集
MSDN

は、「ラムダ式の基本的なタイプは、汎用のFuncデリゲートの一つです。これは、ラムダ式を渡すことが可能になりますデリゲートに明示的に割り当てなくてもパラメータとして使用できます。

答えて

5

ウィンドウコントロールは、スレッドの親和性を持っているので、あなたが持っている2つのオプション:

  1. クエリで作業者に国家として
  2. クエリそれをそれを渡す例えば、あなたのスレッドのコードを実行する前にこのデータ

    :最初は簡単ですので、私は2番目用いて捕獲変数の例をあげる

Control.Invokeを経由して労働者

delegate {...}内のビットは、周囲のコードがワーカースレッド上にある場合でも、UIスレッドで発生します。上記のいずれかを内に混ぜて funcにするか、スレッドを切り替えた後でfunc全体を呼び出すことができます。

2

その代理人にControl.Invokeを呼び出すか、代理人がそれを呼び出す必要があります。 ラムダ式を使用しても、Windowsフォームのスレッド要件は変更されません。デリゲートを作成しやすくするだけです。

あなたはこれを行うための便利なメソッドを作りたいかもしれません:

// (Untested) 
public static Func<TControl, TResult> WrapInvocation(Func<TControl,TResult> func) 
    where TControl : Control 
{ 
    return control => { 
     return (TResult) control.Invoke(func); 
    }; 
} 

を使用して:

Func<ComboBox, string> getCurrentValue = s => s.SelectedValue.ToString(); 
getCurrentValue = WrapInvocation(getCurrentValue); 

が次にあなたが任意のスレッドから getCurrentValue(comboBox)を呼び出すことができます。

1

問題はこのように、あなたが他のスレッド内Invokeメソッドを呼び出す必要があり、UIコントロールがUIスレッド上でのみを使用することができることを

です:

Func<ComboBox, string> getCurrentValue = 
    s => s.Invoke(new Func<object>(() => s.SelectedValue)).ToString(); 

Invoke方法は、Aとりますデリゲートし、UIスレッドで実行します。

1

一般的に言えば、作成されたスレッド以外のスレッドからUIコントロールにアクセスすることはできません。これを克服するには、該当するコントロールのISynchronizeInvoke.InvokeRequiredをチェックするか、デリゲートなどを呼び出すか、SynchronizationContextを使用する必要があります。

var synchronizationContext = WindowsFormsSynchronizationContext.Current; 
string currentValue = "";  

synchronizationContext.Send(
    () => currentValue = getCurrentValue(comboBox), 
    null); 
0

スレッドは単純にコンボボックスを読んする場合実用的にはコンボボックスの値をつかむスレッド上のイベントハンドラを持つことが、おそらくある場合は、最良の選択肢:秒1はかなりエレガントであるのに対し、最初のオプションは、非常に面倒ですそれが変更されるといつでも、その値を任意のスレッドから読み取ることができるプロパティを介して公開します。

関連する問題