简体   繁体   English

Form.Invoke冻结UI

[英]Form.Invoke freezes the UI

I have been googling around for about an hour, and I still don't found any solution. 我已经搜寻了大约一个小时,但仍然找不到任何解决方案。

I simply try to set the maximum value of a progressbar from another thread. 我只是尝试从另一个线程设置进度条的最大值。 So I found the Control.Invoke method. 所以我找到了Control.Invoke方法。 I've been going ahead and implement it: 我一直在执行它:

在此输入图像描述

Now, when I debug my App it simply stucks at the this.Invoke line. 现在,当我调试我的应用程序时,它只是停留在this.Invoke行上。 The UI comes up, and it is frozen. UI出现,并且被冻结。 So I was going ahead and google that out, and it told me to use this.BeginInvoke() . 因此,我要继续进行搜索并将其搜索出来,它告诉我使用this.BeginInvoke() I implemented it, and I was fine, the UI don't freeze. 我实现了它,很好,UI不会冻结。 Thats quiet nice, but in fact the maximum value of my progress bar didn't change :( 不错,但是实际上我的进度条的最大值没有改变:(

What am I doing wrong? 我究竟做错了什么?

EDIT: Maybe that helps: I am using Parallel.Invoke(); 编辑:也许有帮助:我正在使用Parallel.Invoke(); to manage my thread ... 管理我的线程...

Control.Invoke will only block when it is called on a worker thread and the UI thread is blocked. 仅在工作线程上调用Control.Invoke且UI线程被阻止时, Control.Invoke才会阻止。

The code you posted is correct. 您发布的代码是正确的。 You must be blocking the UI thread somewhere else. 您必须在其他地方阻止UI线程。

I use something similar below in my application which I use to update the actual value for the progress bar. 我在应用程序中使用下面类似的内容,用于更新进度条的实际值。 I have changed it a bit from your example. 我已经从您的示例中对其进行了一些更改。 Give it a whirl and see if it helps :) 旋转一下,看看是否有帮助:)

    public void SetMax(int value)
    {
        if (this.ProgressBar_status.InvokeRequired)
        {
           this.BeginInvoke(new Action<int>(SetMax), value);
           return;
        }
        this.ProgressBar_status.Maximum = value;
    }

I had the same problem and thanks to Nicholas' answer I realised I had fallen into the same trap in a GUI app to debug a class used in a windows service. 我遇到了同样的问题,由于尼古拉斯的回答,我意识到自己陷入了一个GUI应用程序中的同一个陷阱,以调试Windows服务中使用的类。 The service class runs most of it's code in a thread. 服务类在线程中运行大多数代码。 The thread was calling back to a logging procedure when it stopped. 线程停止时正在回调记录程序。 I was stopping it using a button, and the logging used invoke to update a textbox. 我使用按钮停止它,并且日志记录使用了调用来更新文本框。 The problem was so simple I kicked myself - the invoke was waiting for the button-click to finish, which was waiting for the class to stop which was waiting for invoke to log that it was stopping (repeat until task-manager end process). 这个问题是如此简单,我踢了自己-调用正在等待按钮单击完成,它正在等待类停止,而该类正在等待调用记录以使其停止(重复执行,直到任务管理器结束过程为止)。 Solved by creating a thread in the stop button click, with a threadproc to stop the service class. 通过在停止按钮中单击创建线程来解决,使用threadproc来停止服务类。 This meant I had to put more code to update form after the stop in another invoke from the new thread, but that worked ok as it wasn't waiting for the main form thread. 这意味着我不得不在停止之后在新线程的另一次调用中放置更多代码来更新表单,但是这样做没问题,因为它没有等待主表单线程。

In my case, mistake was using join() after starting thread. 就我而言,错误是在启动线程后使用join() join() prevents main thread from execution of codes before child thread completion. join()防止主线程在子线程完成之前执行代码。 I removed join() command and moved codes after join() to thread and everything worked fine. 我删除了join()命令,并在join()之后将代码移至线程,一切正常。

I would suggest it is better to use Background worker component which supports reporting progress in the progress bar including other features rather than to call invoke and BeginInvoke. 我建议最好使用支持工作进度条(包括其他功能)中的进度报告的后台工作程序组件,而不是调用invoke和BeginInvoke。 You can find more details about background worker at below MSDN link: 您可以在下面的MSDN链接中找到有关后台工作者的更多详细信息:

http://msdn.microsoft.com/en-us/library/c8dcext2.aspx http://msdn.microsoft.com/en-us/library/c8dcext2.aspx

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

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