Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在新线程打开的新窗口中更新文本框?_C#_Wpf_Multithreading - Fatal编程技术网

C# 如何在新线程打开的新窗口中更新文本框?

C# 如何在新线程打开的新窗口中更新文本框?,c#,wpf,multithreading,C#,Wpf,Multithreading,我能够通过以下代码在新线程中打开一个新窗口 以下代码来自MainWindow.xaml.cs private void buttonStartStop_Click(object sender, RoutedEventArgs e) { Test test = new Test(); Thread newWindowThread = new Thread(new ThreadStart(test.start)); newWindowThread.SetApartmentSt

我能够通过以下代码在新线程中打开一个新窗口

以下代码来自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 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); }));
}
“Begin”确实会打印在文本框中,但“FINAL”不会,我希望Test类中的start方法在整个程序中更新outputwindow中的文本框。最好的方法是什么


提前谢谢你

我不知道你想做什么。FINAL不打印是正常的,因为您调用了System.Windows.Threading.Dispatcher.Run()。此方法使线程保持活动状态并侦听事件。您可以将其视为在Run方法中有while(true){}。方法将继续运行,直到Dispatcher关闭。当需要设置消息时,应该保持后台线程的活动状态,并从另一个线程调用静态方法。下面是一个例子:

        // 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();
//在另一个线程中引用窗口
窗口输出窗口=null;
线程线程=新线程(()=>
{
//另一根线
outputWindow=新窗口();
outputWindow.Show();
//运行事件循环
System.Windows.Threading.Dispatcher.Run();
}){ApartmentState=ApartmentState.STA,IsBackground=true};
thread.Start();
while(outputWindow==null)
{
//等待另一个线程中的窗口被创建
睡眠(100);
}
//模拟过程
对于(int i=0;i<10;i++)
{
outputWindow.Dispatcher.BeginInvoke((操作)(()=>{outputWindow.Title=i.ToString();}),System.Windows.Threading.DispatcherPriority.Normal);
Thread.Sleep(500);//模拟一些艰苦的工作,以便我们可以看到另一个窗口标题上的更改
}
//关闭窗口或关闭调度程序或中止线程。。。
thread.Abort();
编辑:

这可能是一个快速而肮脏的通用解决方案。DoSomeWork为显示进度信息的等待窗口创建另一个GUI线程。此窗口创建实际执行工作的工作线程。工作在方法操作中实现。第一个参数是等待窗口,所以您可以从工作线程更改它。当然,在现实世界中,您应该通过接口,而不是直接到窗口实现,但这只是一个示例。第二个参数是object,所以您可以将所需的任何内容传递给工作线程。如果需要更多参数,请传递对象[]或修改方法签名。在这个例子中,我用计数器和睡眠来模拟艰苦的工作。您可以多次单击按钮执行此代码,您将看到所有等待窗口都在不冻结的情况下计数自己的计数器。代码如下:

    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);
    }
publicstaticvoiddosomework(操作待办事项、对象操作参数)
{
线程窗口线程=新线程(()=>
{
窗口等待窗口=新窗口();
waitWindow.Loaded+=(s,e)=>
{
线程工作线程=新线程(()=>
{
//在通过
//等待窗口作为参数
toDo(waitWindow,actionParams);
}){IsBackground=true};
//启动工作线程。
workThread.Start();
};
waitWindow.Show();
Dispatcher.Run();
}){ApartmentState=ApartmentState.STA,IsBackground=true};
//启动等待窗口线程。
//当窗口加载时,它将创建工作线程并启动它。
windowThread.Start();
}
私有void MyWork(窗口等待窗口,对象参数)
{
对于(int i=0;i<10;i++)
{
//通过等待窗口向用户报告进度。
waitWindow.Dispatcher.BeginInvoke((操作)(()=>waitWindow.Title=string.Format(“{0}:{1}”,参数,i)),DispatcherPriority.Normal);
//模拟长时间工作。
睡眠(500);
}
//工作完成。关闭等待窗口dispather。
//这将停止侦听事件,并最终终止
//等待窗口线程。
waitWindow.Dispatcher.InvokeShutdown();
}
私有无效按钮1\u单击(对象发送者,路由目标)
{
DoSomeHardWork(我的工作,DateTime.Now);
}

理想情况下,创建UI元素的线程(UI线程)也会拥有这些元素。使用dispatcher,您所做的只是将与UI无关的处理推送到后台线程中。后台进程完成后,结果将再次推回到主UI线程。查看示例:

谢谢您的回复和代码。这就是我想做的:1。单击buttonStartStop时,我希望另一个类中的方法在另一个线程中启动和运行。2.“开始”方法将打开一个新窗口,其中包含一个文本框,当它工作时,它将更新文本框以提供用户反馈。为什么不先创建文本框表单,然后新表单可以创建线程并启动它。在这种情况下,我将在当前GUI线程中正常打开窗口,并在后台线程中完成所有其他工作。打开的窗口上的更新可以直接通过GUI调度程序进行。你将如何组织并不重要。只要考虑一下:1。若窗口是在后台线程中创建的,那个么必须将线程设置为STA,并在Show()之后调用Dispatcher.Run()。2.对已打开窗口的所有调用都应通过其dispatcher对象进行。3.“进度信息”窗口不应位于执行处理的同一线程中,否则将被阻止。如果你需要一些代码。。。请评论我。@user1018735谢谢,我希望有一些示例代码。我一直在努力让这一切顺利进行
    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);
    }