2011-06-13 14 views
6

ワーカースレッドからUIスレッドを呼び出すことは多くの場合、Invoke()の代わりにBeginInvoke()を使用する理由がわかっています。私は最近this questionを投稿し、いくつかの調査をした後、UIスレッド上で何かを(非同期に)呼び出すために少なくとも3つの異なる方法(内部的には同じかもしれない)があることが分かった。control.BeginInvoke()対ディスパッチャー対SynchronizationContext Vs .. - 信頼性

  1. Control.BeginInvoke()
  2. Dispatcher.BeginInvoke(priority..)

を使用してSynchronizatoinContextクラス

  • を使用すると、誰もが非同期的にUIスレッドで実行されるメソッドを呼び出すための信頼性の高い方法である私に言うことができます。どんな経験ですか?私はDispatcher.BeginInvokeに優先順位のコンポーネントがあることを確認します。信頼性を高めますか?

    コンテキスト
    我々はsomeControl.BeginInvoke()を使用しますが、時々(残念ながら唯一のエンドユーザーの生産環境における)BeginInvoke isに渡されたデリゲートは、私はそれが作成し、ポストメッセージが迷子にされていることを信じていますこれは実行されないことに気づいています。私たちはUIスレッドに信頼できる方法で通信する必要があります。 control.Invoke()はUIをハングアップすることもあるので、そこに行きたくはありません。

  • +0

    でBeginInvokeメソッドの醜さを置くことができます。 – SLaks

    +0

    私は同様の問題を抱えています...万が一問題を解決できましたか? –

    +0

    ここと同じですか? – Pedro77

    答えて

    0

    BeginInvokeと呼び出しても何も起こらない場合は、環境や呼び出しコードに問題がある可能性があります。BeginInvokeは信頼できません。まあ、バグかもしれないけど、それははるかに少ないです。

    おそらくもっと文脈を与えることができ、私たちは診断を手助けすることができます。

    +0

    お返事ありがとうございます。私のコードでも同様のシナリオがあります。 http://stackoverflow.com/questions/6270514/control-begininvoke-fails-to-call-the-delegate – karephul

    +0

    こんにちはkarephul、それは興味深いですが、彼らは答えを見つけられなかったので、このケースでは大いに役立ちません。スレッド、プロセス、ロックなどの基本設定は何ですか? –

    +0

    ああ...それは同じ問題ですか?ちょうどここに転記されましたか? –

    0

    より多くの場合、SynchronizationContextはより抽象的で適応性があります。特定の実装のラッパーです。 MSDNでは、「同期モデルのプロバイダはこのクラスを拡張し、これらのメソッドの独自の実装を提供できます」と述べています。

    +0

    ここではSynchronizationContextが推奨されています。http://social.msdn.microsoft.com/Forums/en-US/async/thread/1218c86e-fa9b-45a6-93b0-5e27616a6c21 – Steel

    0

    ラムダ関数とBeginInvokeには注意が必要です。私はこのようなコードを持っていて、あらゆる種類の奇妙な行動を起こしました。

    MyThing thing; 
    while(GetThing(ref thing)) { 
        control.BeginInvoke((Action)(() => control.Text = thing.ToString())); 
    } 
    

    問題は、ラムダ関数を作成するときにthingが評価されていないということです。 lamdba関数が実行されたときに評価されます。しかし、これは、プロデューサスレッドで同時に変化する変数にバインドされています。

    あなたはthing

    MyThing thing; 
    while(GetThing(ref thing)) { 
        MyThing thing_x = thing; 
        control.BeginInvoke((Action)(() => control.Text = thing_x.ToString())); 
    } 
    

    のローカル変数のコピーを宣言することでこの問題を解決することもできますし、WPFとWinFormsのを混同しないでくださいラッパー

    MyThing thing; 
    while(GetThing(ref thing)) { 
        SetText(thing); 
    } 
    
    void SetText(MyThing thing) 
        control.BeginInvoke((Action)(() => control.Text = thing.ToString())); 
    } 
    
    関連する問題