2011-11-08 26 views
0

私は最近これについての投稿をしましたが、私の最後の質問はよく書かれていなかったと私は答えを得たと思うが、私は最後のものが混乱しているように単純な解決策があるかどうかを見たい。今回私はできるだけ明瞭にそれを書こうとしました。新しいスレッドが新しいウィンドウを開く、新しいウィンドウでテキストボックスを更新する方法?

私はここにWPFアプリケーションの次のコードを持っているがMainWindow.xaml.csからコード

コードが

public MainWindow() 
{ 
    InitializeComponent(); 
} 

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    Thread[] threads = new Thread[3]; 

    for (int i = 0; i < 3; i++) 
    { 
    int index = i; 
    threads[i] = new Thread(new ThreadStart(test)); 
    threads[i].SetApartmentState(ApartmentState.STA); 
    threads[i].IsBackground = true; 
    threads[i].Start(); 
    } 
} 

public void test() 
{ 
    OutputWindow outputwindow = new OutputWindow(); 
    outputwindow.Show(); 
    System.Windows.Threading.Dispatcher.Run(); 

    outputwindow.textBox1.Text = "writing"; 
    //some more stuff done 
    //some more stuff done 
    //some more stuff done 
    outputwindow.textBox1.Text = "\nmore writing"; 
    //some more stuff done 
    //some more stuff done 
    //some more stuff done 
    outputwindow.textBox1.Text = "\nmore writing"; 
} 

どのように私は(textBox1.Textが実際にテストとして更新されますすることができます)です実行されていますか?

よろしくお願いいたします。あなたの答えのための

EDIT

おかげで、私はそれがまだ動作させることができませんでした。

これはネットワークアプリケーションなので、タイムアウト、ping、およびプログラム全体で多くの情報を印刷して、すべてが計画どおりに進行していることを確認したいので、テキストボックスがデータバインディングより適していると思います。

私はあなたの答えのいくつかを試しましたが、動作させることができませんでした。これは私が試した最後の例ですが、うまくいきません。

public MainWindow() 
{ 
    InitializeComponent(); 
} 

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    Thread[] threads = new Thread[3]; 

    for (int i = 0; i < 3; i++) 
    { 
    int index = i; 
    threads[i] = new Thread(new ThreadStart(test)); 
    threads[i].SetApartmentState(ApartmentState.STA); 
    threads[i].IsBackground = true; 
    threads[i].Start(); 
    } 
} 

public void test() 
{ 
    OutputWindow outputwindow = new OutputWindow(); 
    outputwindow.Show(); 
    System.Windows.Threading.Dispatcher.Run(); 

    outputwindow.textBox1.Text = "writing"; 
    //some more stuff done 
    //some more stuff done 
    //some more stuff done 
    outputwindow.textBox1.Text = "\nmore writing"; 
    //some more stuff done 
    //some more stuff done 
    //some more stuff done 
    Action action =() => outputwindow.textBox1.Text = "\nmore writing"; 
    Dispatcher.Invoke(action); 
} 

答えて

1

私はあなたの最後の質問に答えて、私はこれを見ました。私はあなたがもう一度意見を出したかったと結論したので、あなたはもう一度尋ねました。私はこれに答えるつもりはありませんでしたが、あなたが遠くに行っていないのを見ました。

コードサンプルの問題は、Dispatcher.Run()を呼び出すことです。問題は、実際にウィンドウをテキストボックスでアクティブに保つためにDispatcher.Runを呼び出す必要がありますが、Dispatcher.Runメソッドは無限ループです。あなたはDispatcherで立ち往生しています。Dispatcherがシャットダウンされてウィンドウが閉じられるまで、コード行を実行します。そのときだけあなたのコードは継続してそれらのoutputWindow.textBox1.Text set文を実行しますが、今は遅すぎます。あなたの問題への解決策は、あなたの「作業コード」からoutputWindowを分離することです。

コードの最も簡単な変更は、Dispatcher.Run()でブロックされないように、別のスレッドに「作業コード」を入れることです。サンプルコードをどのように表示するかは同じです(同じメソッドでoutputWindowを作成する方が望ましいからです)。

// all good here 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    // also all good here 
    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     Thread[] threads = new Thread[3]; 

     for (int i = 0; i < 3; i++) 
     { 
      int index = i; 
      threads[i] = new Thread(new ThreadStart(test)); 
      threads[i].SetApartmentState(ApartmentState.STA); 
      threads[i].IsBackground = true; 
      threads[i].Start(); 
     } 
    } 

    // here's the change 
    public void test() 
    { 
     OutputWindow outputwindow = new OutputWindow(); 
     outputwindow.Show(); 

     // here you create another thread which will execute your work code (the one you had after the Dispatcher.run statement 
     Thread workThread = new Thread(new ParameterizedThreadStart(workMethod)); 
     workThread.IsBackground = true; 
     // start the work thread BUT transfer the reference to outputwindow 
     workThread.Start(outputwindow); 

     System.Windows.Threading.Dispatcher.Run(); 

     // no more code here; it has been transferd to workMethod which runs in another thread 
    } 

    public void workMethod(object threadParam) 
    { 
     OutputWindow outputwindow = (OutputWindow)threadParam; 

     // those are little ugly but you must go through dispatcher because you are now in a different thread than your outputwindow 
     outputwindow.Dispatcher.BeginInvoke((Action)(() => { outputwindow.textBox1.Text = "writing"; }), System.Windows.Threading.DispatcherPriority.Normal); 
     //some more stuff done 
     //some more stuff done 
     //some more stuff done 
     outputwindow.Dispatcher.BeginInvoke((Action)(() => { outputwindow.textBox1.Text = "\nmore writing"; }), System.Windows.Threading.DispatcherPriority.Normal); 
     //some more stuff done 
     //some more stuff done 
     //some more stuff done 
     outputwindow.Dispatcher.BeginInvoke((Action)(() => { outputwindow.textBox1.Text = "\nmore writing"; }), System.Windows.Threading.DispatcherPriority.Normal); 

     // and finally close the outputWindow 
     outputwindow.Dispatcher.InvokeShutdown(); 
    } 
+0

ありがとうございます。どうもありがとう。 – Arya

+0

ウィンドウが閉じているときに作業メソッドが動作を停止させるためにとにかくありますか?今は、毎秒Console.beep()を使用して無限ループで試してみました。ウィンドウを閉じても、ビープ音が鳴ります。 – Arya

+0

代わりにタブを使用し始めましたが、よりうまく動作します – Arya

0

コントロールを更新するにはdispatherでinvokeを使用する必要があります。 以下のリンクを参照できます。

http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher http://www.albahari.com/threading/part2.aspx#_Rich_Client_Applications

+0

私はhttp://www.albahari.com/threading/part2.aspx#_Rich_Client_Applicationsからの例を試してみましたが、私は、コードを貼り付けるために私のポストを編集し、それはまだ動作しません。 – Arya

0

問題は更新は、現在のメソッドが終了するまでに処理されないことです。現在のメソッドが終了する前にメッセージポンプを適用するには、メッセージポンプをポンプする必要があります。これを行う方法の例についてはhereを参照してくださいと述べ

public static void DoEvents(this Application application) 
{ 
    Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new VoidHandler(() => { })); 
} 

private delegate void VoidHandler(); 

が、私はあなたのデザインが望むされ、大幅なBackgroundWorkerなどより標準的なメカニズムを利用することによって改善することができると思います。

0

他の誰もがここに書いているので、あなたはUIオブジェクトを変更したい場合に呼び出す必要があります。しかし、おそらくデータバインディングを代わりに使用するよう教えてもらえますか?これはWPFを使用して実際にデータをバインドするのに最適な方法です(あなたの場合は文字列)。

はいくつかここにチュートリアルがあります:あなたもMVVMパターンに見えるしたい長期的にhttp://www.wpftutorial.net/DataBindingOverview.html

が、それはデータバインディングの使用を開始するには、少なくともスタートです。

関連する問題