我做了一个C#winforms应用程序。现在我有一个有很多按钮的表单,它调用了大量的数字运算函数,其输出我在文本框中更新。我调用textbox.begininvoke()方法,我将委托传递给更新文本框中文本的函数,但是当文本很大时,表单没有响应,因为我无法单击取消按钮。是不是有任何方式使整个表单保持响应,并且更新也不断发生。我必须向用户显示数据,因为它即将到来,我无法缓冲整个事情并最终显示。我还尝试实现自己的缓冲区并以特定的时间间隔显示数据,这对于少量文本很有用,但是大量的UI只是没有响应。 任何帮助? 感谢
在出现一些混淆时更新问题
答案 0 :(得分:9)
调用BeginInvoke(或Invoke)不会为你买任何东西,除非数字运算功能在另一个线程上运行,而不是UI线程。
请考虑以下代码:
private void HardWork(object state)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
SetText(i.ToString());
}
}
private void SetText(string text)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<string>(SetText), text);
}
else
{
textBox1.Text = text;
}
}
private void Button_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(HardWork);
}
Button_Click
方法将在单独的线程上开始执行方法HardWork
。 HardWork将进行一些处理(通过Thread.Sleep
调用模拟)然后调用方法来显示一些进度。在这个方法中,我们需要检查我们是否在UI线程上。如果我们不是,我们使用Invoke
(或BeginInvoke
)调用相同的方法,以强制它在UI线程上执行。
更新:如果从数字运算方法发出的数据量非常大,这当然可能会对UI响应性产生负面影响。例如,如果您在线程方法中累积了大量文本并在每次更新时发出该文本,那么这将比发布自上次更新后发生的更改更慢。文本框也是如此;仅使用新文本调用TextBox.AppendText将比重复分配TextBox.Text属性更快。
很难就如何解决您的特定问题提供更详细的想法,因为我们还没有看到您的代码实际上做了什么。
答案 1 :(得分:7)
你倒退了。
您应该使用BeginInvoke来更新UI。它似乎不会产生新线程,因为你似乎相信。
BeginInvoke只是“在最初创建控件的线程中执行以下操作”,这是您的UI线程。
因此,您应该在数字运算线程中使用BeginInvoke将更新回发到UI中。
希望这有帮助
答案 2 :(得分:-1)
让更新文本框的功能逐个进行,并在每次更新之间调用DoEvents。也就是说,分解字符串......
update piece 1
DoEvents
update piece 2
DoEvents
...
update piece n