使用 control.begininvoke 后 UI 仍然没有响应

发布于 2024-07-21 03:40:43 字数 499 浏览 11 评论 0原文

我制作了一个 C# winforms 应用程序。 现在我有一个带有很多按钮的表单,这些按钮调用大量的数字运算函数,其输出在文本框中更新。 我调用 textbox.begininvoke() 方法,将委托传递给更新文本框中文本的函数,但是当文本很大时,表单不响应,因为我无法单击取消按钮。 有没有办法让整个表单保持响应并且更新也不断发生。 我必须在数据到来时向用户显示数据,我无法缓冲整个数据并最终显示。 我还尝试实现自己的缓冲区并以特定的时间间隔显示数据,这对于少量文本非常有用,但对于大量文本,UI 就没有响应。 有什么帮助吗? 感谢

更新问题,因为出现了一些混乱

  • 我在单独的线程上调用了数字处理函数。
  • 每当数据到达时,该数字处理函数都会调用 control.begininvoke 函数来更新文本框,
  • 我的 UI 将被显示,并且我看到输出即将到来,但是当数据很大时,我无法执行任何其他活动,尽管我仍然可以看到用户界面

i've made a C# winforms application. Now i have a form which has lots of buttons, which call huge number crunching functions whose output i update in a textbox. I call the textbox.begininvoke() method to which i pass a delegate to the function which updates the text in the textbox, however when the text is huge, the form is non responsive as i can't click on the cancel button. Isn't there any way so that the whole form remains responsive and as well the update too keeps happening. I have to show the data to the user as it is coming, i can't buffer the whole thing and show in the end. I also tried to implement my own buffer and show data at particular intervals which works great for small amount of text, but in huge amount the UI just doesn't respond.
any help?
Thanks

updating question as some confusions are arising

  • i've called the number crunching function on a separate thread.
  • that number crunching function calls the control.begininvoke function whenever data arrives to update the textbox
  • MY UI gets to be displayed and i see the output coming, but when the data is huge, i can't do any other activity though i can still see the UI

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑,眼淚并存 2024-07-28 03:40:43

调用 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 属性更快。

很难就如何解决您的特定问题提供更详细的想法,因为我们还没有看到您的代码实际做了什么。

Calling BeginInvoke (or Invoke) will not buy you anything unless the number crunching function is running on another thread than the UI thread.

Consider the following code:

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);            
}

The Button_Click method will start executing the method HardWork on a separate thread. HardWork will do some processing (simulated by the Thread.Sleep call) and then call a method to display some progress. Inside this method, we need to check whether we are on the UI thread or not. If we are not, we invoke the same method using Invoke (or BeginInvoke) in order to force it to execute on the UI thread.

Update: if the amount of data emitted from the number crunching method is very large, this might of course have a negative impact on the UI responsiveness. If you for instance accumulate a large amount of text in your threaded method and emit that text on every update, that will be slower than just emitting what has changed since the last update. The same goes for the text box; calling TextBox.AppendText with just the new text will be faster than repedetly assigning the TextBox.Text property.

It's hard to give more detailed ideas on how to solve your particular problem since we have not see what your code actually does.

素罗衫 2024-07-28 03:40:43

你把它搞反了。

您应该使用 BeginInvoke 来更新 UI。 正如您似乎相信的那样,它不会产生新线程。

BeginInvoke 只是“在最初创建控件的线程中执行以下操作”,即您的 UI 线程。

因此,您应该在数字处理线程中使用 BeginInvoke 将更新发回 UI。

希望这可以帮助

You got it backwards.

BeginInvoke is what you should use to update the UI. It does not spawn a new thread, as you seem to believe.

BeginInvoke is simply "Execute the following within the thread that the control was originally created in", which is your UI thread.

BeginInvoke is therefore what you should use in your number crunching thread to post back updates into the UI.

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文