简体   繁体   English

C# 从程序线程更新表单(richTextBox 和 toolStripStatusLabel)

[英]C# Updating form (richTextBox and toolStripStatusLabel) from Program thread

I'm trying to take a console application and build a gui for it.我正在尝试使用控制台应用程序并为其构建 gui。 I've got the main functions of my GUI working and added the console application files to my new project.我已经使用了 GUI 的主要功能,并将控制台应用程序文件添加到我的新项目中。 I changed the namespace of the files to match that of the winform application and moved the main function of the console application into the Program class defining it as a function taking a CSV path argument which it gets from the form.我更改了文件的命名空间以匹配 winform 应用程序的命名空间,并将控制台应用程序的主函数移到 Program 类中,将其定义为一个函数,该函数采用从表单获取的 CSV 路径参数。

So it appears that program it functioning but Im having trouble getting the form to update.因此,该程序似乎可以正常运行,但我无法更新表单。 There are some Console.WriteLine() functions that I want to write to the toolStripStatusLabel and others to the richTextBox.我想将一些 Console.WriteLine() 函数写入 toolStripStatusLabel 并将其他函数写入 RichTextBox。

I'm new to C# and the main program wasnt written by me but Im trying to build on it.我是 C# 的新手,主程序不是我写的,但我试图在它的基础上构建。

Program.cs程序.cs

Form1 Frm1 = new Form1();
Frm1.UpdateStatusBar("Sorted jobs by EDD....");
Frm1.Refresh();

Form1.cs表格1.cs

public void UpdateStatusBar(string status)
{
    Form1 Frm1 = new Form1();
    Frm1.toolStripStatusLabel1.Text = status;  
}

Pastebin Program.cs See line 92. Pastebin Program.cs见第 92 行。

Pastebin Form1.cs See line 88. Pastebin Form1.cs见第 88 行。

I think, the problem is that: you're trying to create new Form1 anytime trying to UpdateStatusBar().我认为,问题在于:您在尝试 UpdateStatusBar() 的任何时候都试图创建新的 Form1。

You may fix this by:您可以通过以下方式解决此问题:

public void UpdateStatusBar(string status)
{    
    this.toolStripStatusLabel1.Text = status;  
}

As said by @Thinhbk, creating a new Form1 each time you are wanting to update the tool strip is not the way to to go.正如@Thinhbk 所说,每次想要更新工具条时都创建一个新的Form1并不是要走的路。 The other problem you have is that all of the processing is running in the same thread (I looked at the stuff you posted on Pastebin), meaning that you won't see the progress updates until the end anyway.您遇到的另一个问题是所有处理都在同一个线程中运行(我查看了您在 Pastebin 上发布的内容),这意味着无论如何您都不会看到进度更新,直到最后。

To get this working, I first modifed the signature of the public void AX1Program(string path) method to this:为了使其正常工作,我首先将public void AX1Program(string path)方法的签名修改为:

public void AX1Program(Form1 form1, ManualResetEvent resetEvent, string path)

Passing in the form means we can access the UpdateStatusBar method and resetEvent is used to signal when the thread is done. resetEvent表单意味着我们可以访问UpdateStatusBar方法,并且resetEvent用于在线程完成时发出信号。 The body of AX1Program changes to this: AX1Program的主体更改为:

try
{
    ...
    //Do work as per normal
    ...
    form1.UpdateStatusBar("some new status");
}
catch (Exception)
{
    //Any exception handling/logging you may need.
}
finally
{
    //Indicate that we are done.
    resetEvent.Set();
}

Now, to invoke the AX1Program method, you currently have some code (it's in a couple of places in your Writebutton_Click method):现在,要调用AX1Program方法,您当前有一些代码(它位于Writebutton_Click方法的几个位置):

Program Pgm1 = new Program();
Pgm1.AX1Program(CSVtextBox.Text);

We want to invoke this asynchronously, so we would instead go:我们想异步调用它,所以我们改为:

RunAX1Program(CSVtextBox.Text);

Which invokes the following two methods:其中调用了以下两个方法:

private void RunAX1Program(string text)
{
    ManualResetEvent resetEvent = new ManualResetEvent(false);
    ThreadPool.QueueUserWorkItem(RunAX1ProgramDelegate,
        new object[] { resetEvent, text });
}

private void RunAX1ProgramDelegate(object state)
{
    object[] stateArray = (object[])state;
    ManualResetEvent resetEvent = (ManualResetEvent)stateArray[0];
    string text = (string)stateArray[1];

    Program program = new Program();
    program.AX1Program(this, resetEvent, text);
    //Wait until the event is signalled from AX1Program.
    resetEvent.WaitOne();
}

Because we are now wanting to update the tool strip from another thread, the UpdateStatusBar method will need to look like this so that we can safely modify the controls:因为我们现在想要从另一个线程更新工具条, UpdateStatusBar方法需要如下所示,以便我们可以安全地修改控件:

public void UpdateStatusBar(string status)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke((MethodInvoker)delegate
        {
            UpdateStatusBar(status);
        });
    }
    else
    {
        toolStripStatusLabel1.Text = status;
    }
}

You could then use a similar pattern to update your rich text box.然后您可以使用类似的模式来更新您的富文本框。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM