2011-11-06 31 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