2012-03-12 11 views
1

私はwpfでGUI要素を生成する1つのスレッドを持っています。スレッド WPFキャンバス(...ように長方形と)オブジェクトを描画することがありTask.Factoryとスレッド間の通信

このは、別のスレッドがさんはそれを計算スレッドに名前を聞かせて呼び出します。このスレッドは、キャンバスに表示される要素のサイズや位置などを計算します。

私はこれらの2つの部分(GUIと計算)を別のスレッドで実行したいと思っています。 「計算スレッド」は、wpf機能への参照がないライブラリに基づいています。

ここで、wpfスレッドで表示される計算スレッドの中間データを表示します。私はそのようにやっている :

カルクスレッドがWPF-スレッドによって実装されているイベント(DATAREADY)を発射する:

void MyRegStringObject_DataReady() 
{ 
    if (DebugMode) 
    MyDrawingBoard.DrawRegElements(); 
} 

問題は今、エラーがスローされていることを、次のとおりです。他のスレッドがそれを所有しているためこのオブジェクトにアクセスすることはできません "

このエラーを参照してstackoverflowでいくつかの回答がありますが、エラーがスローされたコード内のこの位置で

curCanvas.Children.Clear(); 

関数DrawRegElementsは()(とりわけ)キャンバスオブジェクトをクリアしたいと考えています。 calc-threadからのイベントによってトリガーされた関数MyRegStringObject_DataReadyもcalc-threadによって負うようです。しかし、それはwpfスレッドが基づいているクラスで定義されています。

どうすればこの問題を解決できますか?誰にも分かりますか?ところで : カルクスレッドは、この方法と呼ばれていない:

CalcElements = Task.Factory.StartNew<bool>(MyRegStringObject.CalcRegElements); 

は、スレッドが終了すると、私は定義された:それと

CalcElements.ContinueWith((FinishCalcRegElements) => 
{ 
    MyDrawingBoard.DrawRegElements(); 
}, CancellationToken.None, TaskContinuationOptions.None, 
TaskScheduler.FromCurrentSynchronizationContext()); 

問題ありません。 Everythinsは完璧に走ります。 ContinueWithで定義されている関数は、wpf-threadによって保留されているようです。

答えて

2

エラーメッセージは簡単ですが、現在所有しているスレッドからUI要素にアクセスしようとしています。委任UIスレッドにワーカースレッドからのすべてのメッセージを投稿しますメインUIスレッドに関連付けられているWPF Dispatcherにこの作品:

Application.Current.Dispatcher.BeginInvoke((ThreadStart)delegate 
    {    
     MyDrawingBoard.DrawRegElements(); 
    }); 

あなたがメインUIスレッドに関連付けられている、正しいディスパッチャを使用していることを確認するために、ワーカースレッドコードにパラメータとして渡すことができるので、メインUIスレッドからDispatcher.Currentを渡すだけです。ワーカースレッドでDispatcher.CurrentDispatcherを呼び出すと、呼び出し側ワーカースレッドに関連付けられた新しいインスタンスが初期化されます。または、メインUIスレッドのDispatcherを参照するApplication.Current.Dispatcherを使用してください。

PS:それはクラスで定義されている

しかし、WPFスレッドがこれは間違った仮定である

に基づいて、クラス自体は任意のスレッドに関連していません。 Concrteteクラスのインスタンスは次のとおりです。したがって、UIまたは非UI関連のクラスをUIまたはワーカースレッドのいずれかで作成できます。

また、スレッドDataReadyイベントが発生した重要なポイントは?

+0

'Dispatcher.CurrentDispatcher](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher.aspx)という意味の' Dispatcher.Current'と言うときは、そうですか?私はMyDrawingBoardがWPFコントロールのようなものだと思うので、 'MyDrawingBoard.Dispatcher.BeginInvoke'はOKです。 – Clemens

+0

右 'CurrentDispatcher'が修正されました。あなたはこれを試しましたか? – sll

+0

@ sll Dispatcher.CurrentDispatcher.BeginInvokeは実際には機能しません理由はわかりませんが、UIスレッドはワーカースレッドによって発生したイベントを受け取りますが、DrawRegElementsは呼び出されません。終了時(ワーカースレッドが終了したとき)にのみ呼び出されます。 – manton

関連する問題