2011-10-18 4 views
0

上で実行するためにTaskScheduler /のSynchronizationContextを取得します。このコードはUIスレッド上で実行され、UIスレッドで発生したスレッドに関係なくイベントを処理するために設計されています。すべての処理が行われてしまうところそれは、スレッド1のようになりますでしょうは、WPFのViewModelのために以下のコードを考えてみて特定のスレッド

ChangeManager init on thread=1 
ModelChanged on thread=3 
ModelChanged on thread=3 
ModelChanged on thread=7 
ModelChanged on thread=9 

私の期待:これは出力を実行します

しかし

は、のようなものです。私がこのようなSynchronizationContextを直接使用しようとしても、

protected void Init() 
{ 
    Debug.WriteLine(string.Format("ChangeManager init on thread={0}", Thread.CurrentThread.ManagedThreadId));   

    this.uiContext = SynchronizationContext.Current;   

    modelChanged = (o, args) => uiContext.Post((ignore) => { 
     Debug.WriteLine(string.Format("ModelChanged on thread={0}", Thread.CurrentThread.ManagedThreadId)); 
     this.ModelChanged(o, args); 
    } 
    , null); 
} 

...同じことが分かります。

私の考え方やアプローチには何か問題はありますか?どのようにしてイベントをinitスレッドで処理するのですか?

ありがとうございます!

答えて

2

興味深いことに、あなたのコードは私に役立ちます。問題を説明できるコードの部分を省略したのかもしれません。あなたは問題のより完全な再現を投稿できますか?特に、ラムダを割り当てる以外に、modelChangedメンバーで何をしているのかを示してください。

私がしたことは、空のWPFアプリケーションを作成し、メインウィンドウのコンストラクタからInitメソッドを実行することでした。

その後、modelChangedデリゲートを直接呼び出すバックグラウンドスレッドを開始しました。

私は、 "ModelChanged on thread ..."という行が常に正しいスレッド(Initを呼び出したもの)を表示していることを確認しました。

それは任意のヘルプだ場合は、ここにあなたがそれを見て、多分あなたは異なっやっていることについて投稿することができ、私はそれを再現しようとするやったことだ:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     Init(); 
    } 

    private EventHandler modelChanged; 

    protected void Init() 
    { 
     Trace.WriteLine(string.Format("ChangeManager init on thread={0}", 
       Thread.CurrentThread.ManagedThreadId)); 

     var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

     modelChanged = (o, args) => Task.Factory.StartNew(() => 
     { 
      Trace.WriteLine(string.Format("ModelChanged on thread={0}", 
       Thread.CurrentThread.ManagedThreadId)); 

      if (ModelChanged != null) 
      { 
       ModelChanged(o, args); 
      } 
     }, 
      CancellationToken.None, 
      TaskCreationOptions.None, 
      uiTaskScheduler); 
    } 

    public event EventHandler ModelChanged; 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     var t = new Thread(
      obj => 
       { 
         Trace.WriteLine(string.Format(
          "Launching handler on thread={0}", 
          Thread.CurrentThread.ManagedThreadId)); 

         modelChanged(null, EventArgs.Empty); 
       }); 
     t.Start(); 
    } 
} 
0

は、あなたのケースInit() ISN」内のように見えますUIスレッドを実行しています。 Dispatcherプロパティを何かがUIスレッド上で動作する、あなたには、いくつかのコントロールの(例えばWindowさん)を使用することができることを確認し、そのようなUIスレッド上でコードを実行するためにそれを使用するには:

someControl.Dispatcher.Invoke(() => { /* do something with the UI */ }); 

Invoke()のこの特定のオーバーロードは、 System.Windows.Presentation.dllおよびusing System.Windows.Threading;ディレクティブへの参照が必要な拡張メソッドで、.NET 3.5 SP1以上が必要です。

関連する問題