【问题标题】:Appending To TextBox From Another Class and Thread C#从另一个类和线程 C# 附加到 TextBox
【发布时间】:2013-02-28 19:45:24
【问题描述】:

我有一个设置和显示文本框的表单。在表单加载方法中,我从一个完全独立的类名Processing开始一个新线程:

    private void Form1_Load(object sender, EventArgs e)
    {
        Processing p = new Processing();
        Thread processingThread = new Thread(p.run);
        processingThread.Start();
    }

这里是处理类。我想做的是在Utilities 类中创建一个方法,该方法允许我从我需要的任何类更新文本框:

public class Processing
{        
    public void run()
    {               
        Utilities u = new Utilities();

        for (int i = 0; i < 10; i++)
        {
            u.updateTextBox("i");
        }                    
    }

 }

最后是Utilites 类:

class Utilities
{
    public void updateTextBox(String text) 
    {
        //Load up the form that is running to update the text box
        //Example:  
        //Form1.textbox.appendTo("text"):
    }
}

我已经阅读了Invoke 方法、SynchronizationContext、后台线程和其他所有内容,但几乎所有示例都使用与 Form 线程相同的类中的方法,而不是来自单独的类。

【问题讨论】:

  • 使用单独的线程更改界面时要小心;你可能会遇到几个例外。他们通常建议界面更改不要离开它所在的当前线程。
  • 什么UI技术,WPF,WinForms?在 WPF 中,Dispatcher 使这种操作非常简单......
  • 您没有指定您使用的 .NET 框架的版本,但如果您使用的是 .NET 4.5,请考虑使用async/await 来保持您的 UI 响应式一个线程。

标签: c#


【解决方案1】:

Progress 类是专门为此设计的。

在您的表单中,在启动后台线程之前,创建一个Progress 对象:

Progress<string> progress = new Progress<string>(text => textbox.Text += text);

然后将 progress 对象提供给您的工作方法:

Processing p = new Processing();
Thread processingThread = new Thread(() => p.run(progress));
processingThread.Start();

然后处理器可以报告进度:

public class Processing
{        
    public void run(IProgress<string> progress)
    {               
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(1000);//placeholder for real work
            progress.Report("i");
        }                    
    }
}

Progress 类在内部将捕获它首次创建的同步上下文,并将由于Report 调用而调用的所有事件处理程序编组到该上下文,这只是一种花哨的说法代表您转移到 UI 线程。它还确保您的所有 UI 代码都保留在表单的定义内,而所有非 UI 代码都保留在表单之外,有助于将业务代码与 UI 代码分开(这是一件非常好的事情)。

【讨论】:

    【解决方案2】:

    我会在您的 Form1 类中添加一个 AppendText() 方法,如下所示:

    public void AppendText(String text) 
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action<string>(AppendText), new object[] { text });
            return;
        }
        this.Textbox.Text += text;
    }
    

    然后从你的实用程序类中,这样调用它:

    class Utilities
    {
        Form form1;   // I assume you set this somewhere
    
        public void UpdateTextBox(String text) 
        {
            form1.AppendText(text);
        }
    }
    

    可以在此处找到对 .NET 中的线程的非常全面的评论:Multi-Threading in .NET。它有一个关于Threading in WinForms 的部分,对您有很大帮助。

    【讨论】:

    • 我最终按照查理建议的方式进行了操作,尽管进度功能可能是最好的方法。当我有更多的时间时,我会多玩一点。谢谢大家的回答!
    猜你喜欢
    • 2014-07-07
    • 1970-01-01
    • 2015-06-07
    • 2016-12-03
    • 2012-07-21
    • 2013-02-09
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    相关资源
    最近更新 更多