2011-11-06 28 views
0

我可以通過以下代碼在新線程中打開一個新窗口。如何更新由新線程打開的新窗口中的文本框?

下面的代碼是從MainWindow.xaml.cs

private void buttonStartStop_Click(object sender, RoutedEventArgs e) 
{  

    Test test = new Test(); 

    Thread newWindowThread = new Thread(new ThreadStart(test.start)); 
    newWindowThread.SetApartmentState(ApartmentState.STA); 
    newWindowThread.IsBackground = true; 
    newWindowThread.Start(); 
} 

和從test.start()

public void start() 
{ 

    OutputWindow outputwindow = new OutputWindow(); 
    outputwindow.Show(); 


    Output.print("Begin"); 
    System.Windows.Threading.Dispatcher.Run(); 
    Output.print("FINAL"); 
    System.Windows.Threading.Dispatcher.Run(); 

} 

以下而下面是從輸出類

public static void print(String str) 
{ 
    Dispatcher uiDispatcher = OutputWindow.myOutputWindow.Dispatcher; 
    uiDispatcher.BeginInvoke(new Action(delegate() { OutputWindow.myOutputWindow.textBoxOutput.AppendText(str + "\n"); })); 
    uiDispatcher.BeginInvoke(new Action(delegate() { OutputWindow.myOutputWindow.textBoxOutput.ScrollToLine(OutputWindow.myOutputWindow.textBoxOutput.LineCount - 1); })); 
} 

public static void printOnSameLine(String str) 
{ 
    Dispatcher uiDispatcher = OutputWindow.myOutputWindow.Dispatcher; 
    uiDispatcher.BeginInvoke(new Action(delegate() { OutputWindow.myOutputWindow.textBoxOutput.AppendText(str); })); 
    uiDispatcher.BeginInvoke(new Action(delegate() { OutputWindow.myOutputWindow.textBoxOutput.ScrollToLine(OutputWindow.myOutputWindow.textBoxOutput.LineCount - 1); })); 
} 

「開始」不會在文本框中打印,但「FINAL」不會,我想要Test類中的啓動方法更新輸出窗口中的文本框通過程序。做這個的最好方式是什麼?

謝謝你提前

回答

0

我不知道你在做什麼。由於您調用了System.Windows.Threading.Dispatcher.Run(),因此FINAL不打印是正常的。此方法保持線程活着並監聽事件。你可以看看它,如果你在Run方法中有while(true){}。方法將繼續運行,直到分派器關閉。您需要保持後臺線程處於活動狀態,並在需要設置消息時從另一個線程調用您的靜態方法。這裏有一個例子:

 // reference to window in another thread 
     Window outputWindow = null; 

     Thread thread = new Thread(() => 
     { 
      // another thread 
      outputWindow = new Window(); 
      outputWindow.Show(); 
      // run event loop 
      System.Windows.Threading.Dispatcher.Run(); 
     }) { ApartmentState = ApartmentState.STA, IsBackground = true }; 
     thread.Start(); 

     while (outputWindow == null) 
     { 
      // wait until the window in another thread has been created 
      Thread.Sleep(100); 
     } 

     // simulate process 
     for (int i = 0; i < 10; i++) 
     { 
      outputWindow.Dispatcher.BeginInvoke((Action)(() => { outputWindow.Title = i.ToString(); }), System.Windows.Threading.DispatcherPriority.Normal); 
      Thread.Sleep(500); // simulate some hard work so we can see the change on another window's title 
     } 

     // close the window or shutdown dispatcher or abort the thread... 
     thread.Abort(); 

編輯:

這可能是快速&髒通用的解決方案。 DoSomeHardWork爲等待窗口創建另一個GUI線程,顯示進度信息。這個窗口創建了實際完成工作的工作線程。工作在Action方法中實現。第一個參數是等待窗口,所以你可以從工作線程中改變它。當然,在現實世界中,你應該通過界面而不是直接進入窗口實現,但這僅僅是一個例子。第二個參數是對象,因此您可以將所需的任何內容傳遞給工作線程。如果你需要更多的參數傳遞對象[]或修改方法簽名。在這個例子中,我模擬了計數器和睡眠的辛勤工作。您可以多次按下按鈕執行此代碼,您將看到所有等待窗口計數自己的計數器而不會凍結。這裏是代碼:

public static void DoSomeHardWork(Action<Window, object> toDo, object actionParams) 
    { 
     Thread windowThread = new Thread(() => 
     { 
      Window waitWindow = new Window(); 
      waitWindow.Loaded += (s, e) => 
      { 
       Thread workThread = new Thread(() => 
       { 
        // Run work method in work thread passing the 
        // wait window as parameter 
        toDo(waitWindow, actionParams); 
       }) { IsBackground = true }; 
       // Start the work thread. 
       workThread.Start(); 
      }; 
      waitWindow.Show(); 
      Dispatcher.Run(); 
     }) { ApartmentState = ApartmentState.STA, IsBackground = true }; 
     // Start the wait window thread. 
     // When window loads, it will create work thread and start it. 
     windowThread.Start(); 
    } 

    private void MyWork(Window waitWindow, object parameters) 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      // Report progress to user through wait window. 
      waitWindow.Dispatcher.BeginInvoke((Action)(() => waitWindow.Title = string.Format("{0}: {1}", parameters, i)), DispatcherPriority.Normal); 
      // Simulate long work. 
      Thread.Sleep(500); 
     } 
     // The work is done. Shutdown the wait window dispather. 
     // This will stop listening for events and will eventualy terminate 
     // the wait window thread. 
     waitWindow.Dispatcher.InvokeShutdown(); 
    } 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     DoSomeHardWork(MyWork, DateTime.Now); 
    } 
+0

感謝您的回覆和代碼。 這就是我想要做的: 1.當buttonStartStop被點擊時,我想要另一個類中的方法在另一個線程中啓動並運行。 2.「開始」方法將打開一個新的窗口,其中包含一個文本框,因爲它正在工作,它將更新文本框以提供用戶反饋。 – Arya

+0

爲什麼不先創建文本框,然後新的表單就可以創建線程並啓動它。至少,這擺脫了一個sleep()循環。 –

+0

在這種情況下,我會在當前GUI線程中正常打開窗口,並在後臺線程中執行所有其他工作。打開的窗口上的更新可以直接通過GUI調度程序進行。如何組織這一點並不重要。請注意:1.如果窗口是在後臺線程中創建的,則必須將線程設置爲STA並在Show()後調用Dispatcher.Run()。 2。所有對打開的窗口的調用都應該通過它的調度程序對象。 3.「進度信息」窗口不應該在執行處理的同一個線程中,否則它將被阻止。如果你需要一些代碼...評論我。 – user1018735