用C#填充的TextBox

本文关键字:TextBox 填充 | 更新日期: 2023-09-27 18:28:51

我的应用程序中有一个TextBox,用于显示进程状态。像这样的

for(...)
  textbox.text = "new line 'r'n" + textbox.text

问题是,当填充时,没有文本可见,只有白色背景。流程完成后,所有添加的文本都可见。是任何选项,如何解决这个问题(我需要在整个过程中看到文本)。

非常感谢。

用C#填充的TextBox

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        BackgroundWorker bg = new BackgroundWorker();
        bg.DoWork += new DoWorkEventHandler(bg_DoWork);
        bg.RunWorkerAsync();
    }

    delegate void Temp();
    void bg_DoWork(object sender, DoWorkEventArgs e)
    {
        Temp temp = new Temp(UpdateTextBox);
        while (true)
        {
            Thread.Sleep(1000);
            textBox1.BeginInvoke(temp);
        }
    }
    void UpdateTextBox()
    {
        textBox1.Text += "+";
    }
}

如果是winforms,请在循环中添加Application.DoEvents();,以便应用程序可以刷新UI。

这是最简单但不是最佳的方法

编辑:有人在没有解释的情况下否决了这个问题。这是公平的。问题发布者了解幕后工作者,想要一个更简单的解决方案。

无论如何,这个解决方案可以是完美的,这取决于循环的性质。如果它是一个有很多迭代的循环,每个迭代都需要很短的时间来执行,那么调用Application.DoEvents()将非常有效。我从自己的经历中知道这一点。因为这是一个循环,所以很有可能是这样。或者可以在循环中添加几个DoEvents()。它只是检查windows消息队列并处理挂起的工作。

我不认为用户必须继续处理应用程序的其他部分。

如果它是一个迭代次数很少的循环,并且每次执行都需要很长时间,那么就必须使用线程来完成。

但是,请记住,如果一个新手在不太清楚其含义的情况下使用线程,他可能会犯错误(我指的是线程安全)。如果应用程序出现死锁怎么办?损坏不同线程使用的非线程安全结构会怎样?如果用户在后台线程还没有完成的情况下关闭了主窗口,该怎么办?说真的,这个工具在没有经验的人手里可能是一颗炸弹。

此外,如果你想使用线程BackgroundWorker并不是唯一的解决方案。

这是因为只有在方法完成并且清除消息泵以检查"刷新"消息之后,UI才会刷新。

您可以在循环结束时使用Application.DoEvents()。

使用多线程更新文本框。在您的代码中,更新发生得太快,所以您只能看到白色背景。

您的循环正在阻塞主UI线程。因此,一旦控件离开循环,UI就会立即更新。我认为你应该在这里使用BackgroundWorker。你的问题在这篇文章中讨论得很好。希望这会有所帮助。

您需要使用BackgroundWorker从其他线程更新gui,并让gui自己工作(就像在中一样,您可以在gui中执行其他操作,如单击复选框或查看其他内容)。然后使用LogBoxTextAdd方法从另一个线程更新TextBox,这样就不会导致Cross-Thread错误。

using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication4 {
    public partial class Form1 : Form {
        private readonly BackgroundWorker bg = new BackgroundWorker();
        public Form1() {
            InitializeComponent();
            bg.DoWork += doWork;
        }
        private void doWork(object sender, DoWorkEventArgs e) {
            for (int i = 0; i < 15; i++) {
                LogBoxTextAdd("TEST");
            }
        }
        private void LogBoxTextAdd(string varText) {
            if (InvokeRequired) {
                textBox1.Invoke(new MethodInvoker(() => LogBoxTextAdd(varText)));
            } else {
                textBox1.Text = varText + "'r'n" + textBox1.Text;
            }
        }
        private void button1_Click(object sender, EventArgs e) {
            bg.RunWorkerAsync();
        }
    }
}