2017-01-06 9 views
0

私はリッチテキストボックスを持つウィンドウを持っています。どのように新しいスレッドでそれを開き、テキストボックスに書き込むことができますか?新しいスレッドでウィンドウを開き、データを渡す方法は?

私はDispatcher.BeginInvokeでさまざまな方法を試しましたが、ThreadとBackgroundWorkerを使っていましたが、私はそれを正しく設定していません。私は、「呼び出しスレッドは、別のスレッドがそれを所有しているため、このオブジェクトにアクセスできません。窓を開けようとするとき、または書くとき。

私はショーでオープン隠す()、()を使用して非表示の背景ウィンドウを起動します。私は、特定の時間に呼ばリストに保存されているアクションを使用して、それに書き込む

MainWindow mainwindow = this; 

myWindow = new NewWindow(mainwindow); 
myWindow.Left = this.Left + 605; 
myWindow.Top = this.Top + 0; 
myWindow.Hide(); 

myWindow.myRichTextBox.Cursor = Cursors.Arrow; 

を:

簡単にするために
List<Action> LogActions = new List<Action>(); 
Action WriteAction; 

// Create Multiple Actions 
WriteAction =() => 
{ 
    myWindow.myRichTextBox.Document = new FlowDocument(paragraph); 
    paragraph.Inlines.Add(new LineBreak()); 
    paragraph.Inlines.Add(new Bold(new Run("Example")) { Foreground = Brushes.White }); 
}; 
// Add Actions to List 
LogActions.Add(WriteAction); 

// Write All Actions in List 
foreach (Action Write in LogActions) 
{ 
    Write(); 
} 

、それは基本的にやっている:

myWindow.myRichTextBox.AppendText("Example"); 

新しいTHRせずにデータを渡すことができています今すぐead。しかし、リッチテキストボックスが書き込まれているときにマウスが数秒間フリーズすると、フリーズするかもしれないと思った。誰かが新しいスレッドで開くことをアドバイスしますか?

+3

からそれを使用する方法の例ですが、非UIスレッドでコントロールを作成することは非常に複雑です。彼は仕事をするためにメインスレッドと通信する必要があります。たとえば、セカンダリスレッドのリストにアクションをエンキューし、メインスレッドでデキューすることができます(エンキュー/デキュー時にリストをロックすることを忘れないでください)。 – Graffito

+0

@Graffito私は、richtextboxが書かれている間、マウス/メインウィンドウがフリーズするのを止める別の方法があるのでしょうか?これは、アクションの長いリストを一度に約4秒間書きます。 –

+0

メインスレッドでは、タイマーを使用して、私の前のコメントに記載されているアクションをデキューすることができます。 – Graffito

答えて

2

通常は、ユーザーインターフェイスがメインアプリケーションスレッド内にとどまることをお勧めします。このUIでは、バックグラウンドスレッドを生成して実行時間の長いタスクを実行できます。このようにして、UIスレッドは、バックグラウンド作業の進行中にユーザー入力に応答することができます。ウィンドウの場合

、あなたにメッセージを追加したいリッチテキストボックス、myWindowmyWindowは別のスレッドでメッセージを収集して、スレッドの終了時にコールバックを通じてRTFコントロールを更新するためにBackgroundWorkerを使用します(BackgroundWorkerの場合、これはOnRunWorkerCompletedメソッドです)。

ウィンドウを別のスレッドとして実行する必要がある場合、このヘルパークラスは新しいスレッドにWPFウィンドウをラップし、新しいSynchronizationContextを設定します。ただし、通信する場合はスレッドセーフメッセージングが必要です別のスレッドのウィンドウ間。 ConcurrentQueue<T>コレクションは、この目的に役立つスレッドセーフなコレクションを提供します。

public static class WindowThreadHelpers 
{ 
    public static void LaunchWindowInNewThread<T>() where T : Window, new() 
    { 
     Dispatcher.CurrentDispatcher.Invoke(new ThreadStart(ThreadStartingPoint<T>)); 
    } 

    private static void ThreadStartingPoint<T>() where T : Window, new() 
    { 
     SynchronizationContext.SetSynchronizationContext(
      new DispatcherSynchronizationContext(
       Dispatcher.CurrentDispatcher)); 

     var win = new T(); 
     win.Closing += (sender, args) => 
     { 
      Dispatcher.ExitAllFrames(); 
      win.Dispatcher.InvokeShutdown(); 
     }; 

     win.Show(); 
     Dispatcher.Run(); 
    } 
} 

は、ここではそれを簡単にするためにメインスレッド

WindowThreadHelpers.LaunchWindowInNewThread<NewWindow>(); 
関連する問題