2012-01-22 16 views
8

私はオプションウィンドウと、これらのオプションとKinectデータに基づいて色を表示するウィンドウを持っています。これまでのところすべてが1つのスレッド上にあります(私が知る限り、私はスレッドを実行していません)。新しいスレッドでウィンドウを開くにはどうすればよいですか?

ここで、可能な限り低いレイテンシーで更新する必要があるビューアウィンドウを開くオプションを追加します。これはすべてのウィンドウを作成し、それを見せている伴い:

viewer = new SkeletalViewer.MainWindow(); 
viewer.Show(); 

このイベントは、火災、色ウィンドウが(メインスレッド上で1秒間に30回の発射すなわち、イベントが発火を停止)色を表示停止しますが、ビューア完全に表示されます。ビューアとカラーウィンドウの両方を更新したい。

他の質問を読むことから、解決策は新しいスレッドでビューアを作成するように思えます。しかし、私はこれに多くの問題に遭遇しています。

この火災私はビューアを開くためのボタンをクリックします。

private void launchViewerThread_Click(object sender, RoutedEventArgs e) 
    { 
     Thread viewerThread = new Thread(delegate() 
     { 
      viewer = new SkeletalViewer.MainWindow(); 
      viewer.Dispatcher.Invoke(new Action(delegate() 
       { 
        viewer.Show(); 
       })); 
     }); 

     viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception 
     viewerThread.Start(); 

    } 

は関係なく、私は上記のようにviewer.Show()または呼び出し()を呼び出した場合の、行は例外をスロー:はできませんその親Freezableとは異なるスレッドに属するDependencyObjectを使用します。ここで私はInvoke()を理解しています:それは、オブジェクトが実行されているスレッドを知っているビューアのディスパッチャにアクセスし、そのスレッドからメソッドを呼び出すことができます。

新しいスレッドにこのビューアを配置する必要がありますか?問題はスレッドの問題なのでしょうか?ユーザーは視聴者と対話しません。

これはなぜ機能しないのですか?助けてくれてありがとう。

答えて

15

を持っているなら、私に知らせて、それを凍結することなく、メインウィンドウのコントロールを更新することができます。これにより

in the constructor register this 
    public MainWindow() 
    { 
     UpdateColorDelegate += UpdateColorMethod; 
    } 

    // delegate and event to update color on mainwindow 
    public delegate void UpdateColorDelegate(string colorname); 
    public event UpdateColorDelegate updateMainWindow; 

    // launches a thread to show viewer 
    private void launchViewerThread_Click(object sender, RoutedEventArgs e) 
    { 
     Thread t = new Thread(this.ThreadProc); 
     t.Start(); 
    } 

    // thread proc 
    public void ThreadProc() 
    { 
     // code for viewer window 
     ... 
     // if you want to access any main window elements then just call DispatchToMainThread method 
     DispatchToUiThread(color); 
    } 

    // 
    private void DispatchToUiThread(string color) 
    { 
     if (updateMainWindow != null) 
     { 
     object[] param = new object[1] { color}; 
     Dispatcher.BeginInvoke(updateMainWindow, param); 
     } 
    } 

    // update the mainwindow control's from this method 
    private void UpdateColorMethod(string colorName) 
    { 
     // change control or do whatever with main window controls 
    } 

をコード - です窓あなたがエラーを取得している理由です。次に、新しいDispatcherインスタンスを起動して、ウィンドウを管理するランタイムを取得する必要があります。

private void launchViewerThread_Click(object sender, RoutedEventArgs e) 
{ 
    Thread viewerThread = new Thread(delegate() 
    { 
     viewer = new SkeletalViewer.MainWindow(); 
     viewer.Show(); 
     System.Windows.Threading.Dispatcher.Run(); 
    }); 

    viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception 
    viewerThread.Start(); 
} 

で複数のWindows /複数のスレッドの例を参照してください:だから私は新しいウィンドウが新しいスレッドで開くことができませんでした同様の問題に実行していたhttp://msdn.microsoft.com/en-us/library/ms741870.aspx

+0

Show()がビューアのスレッドで呼び出されていることを保証するものとしてInvokeを参照してください。 viewer.Show()の周りのInvoke()がなくても、私はまだFreezableの例外を受け取ります。 –

+0

@ michael.greenwaldその後、例外を引き起こしている何かが 'SkeletalViewer.MainWindow()'にあります。私は上に示したものをまったく実行する空のWPFプロジェクトを構築しましたが、例外なく実行されます。たぶんあなたは問題をこの質問からの似ている:http://stackoverflow.com/questions/3636761/how-to-debug-this-error-when-none-of-my-code-shows-up-in- the-stack – shf301

+0

そして 'launchViewerThread'からそのウィンドウを閉じるには? –

0

私は別のスレッドで実行し、メインウィンドウを更新するdispatcher.beginInvokeを持ってしている、これはあなたの問題を解決しますが、あなたはスレッドPROCを作成してみてくださいすることができます(ビューアウィンドウを開くために)場合はわからない、

ここで

いくつかは、あなたがあなたがいるのと同じスレッド上Show()を呼び出す必要があります任意の質問

+0

ありがとうございました。なぜUIスレッドにカラーをディスパッチするのですか?デフォルトのスレッドであるUIスレッドで呼び出されるメソッドはありませんか? –

+0

メインUIスレッドから分離されたバックグラウンドスレッドは、UIスレッドで作成されたコントロールの内容を更新できないためです。バックグラウンドスレッドがメインウィンドウのコントロールにアクセスするには、バックグラウンドスレッドは、UIスレッドに関連付けられたディスパッチャに作業を委任する必要があります。これは、InvokeまたはBeginInvokeのいずれかを使用して行います。 Invokeは同期で、BeginInvokeは非同期です。操作は、指定されたDispatcherPriorityでDispatcherのイベント・キューに追加されます。 – DotNetUser

+0

このリンクを参照 - http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.begininvoke.aspx – DotNetUser

1

。例外は「別のスレッドに属している依存関係オブジェクトを使用できません」でした。

問題は、ウィンドウがグローバルリソース(背景ブラシ)を使用していたことに終わりました。一度私はブラシのリソースを凍らせ、ウィンドウが正常にロードされます。

関連する問題