问题描述
我是线程领域的新手,但我正在开发的应用程序的某些方面需要我使用 BackgroundWorker 控件来防止 UI 在执行某些文件操作时冻结.
I'm new to the world of threading, but a few aspects of an app I'm working on require me to use a BackgroundWorker control to prevent the UI freezing up while it's doing some file operations.
我正在尝试从 BackgroundWorker 中更新几个表单标签.在我很快发现我无法访问不是在同一个线程中创建的控件之前从未使用过这个,所以经过一些研究,我实现了以下代码,似乎可以让一切正常工作:
What I'm trying to do is update a couple of form labels from within the BackgroundWorker. Having never worked with this before I very quickly discovered that I can't access controls that weren't created within the same thread, so after a bit of research I've implemented the following code that seems to make everything work:
Private Delegate Sub DelegateUpdateStatus(ByVal statusText As String, ByRef currentFile As String)
Private Sub UpdateStatus(ByVal statusText As String, ByVal currentFile As String)
If InvokeRequired Then
Invoke(Sub() LblStatus.Text = statusText)
Invoke(Sub() LblCurrentFile.Text = currentFile)
Else
LblStatus.Text = statusText
LblCurrentFile.Text = currentFile
End If
End Sub
不过,我不明白这段代码在做什么,或者为什么需要它.
Thing is though, I have no understanding of what this code is doing, or why it's required.
我做了一些研究,但我没有对这类事情做过任何实际工作,而且我读过的大多数文章都假设有某种先验知识.
I've done a bit of research but I've not done any real work with this kind of thing, and most articles I've read assume some kind of prior knowledge.
我希望了解的三个主要内容:
The three main things I looking to gain an understanding of:
- 为什么需要这段代码(例如,为什么不能直接从 BackgroundWorker 访问控件)
- 什么是委托,以及何时需要使用它
- Invoke 方法的作用,以及我使用 InvokeRequired 检查的内容
如前所述,线程仍然是一个非常陌生的概念,所以任何简单的英语答案都会非常有帮助 - 谢谢!
As said, threading is still quite a foreign concept, so any answers in plain English would be really helpful - thanks!
感谢大家到目前为止的回复.我做了一些进一步的阅读,我想知道我是否以正确的方式去做.我使用 BackgroundWorker 的原因是为了确保 UI 在我执行文件操作时保持响应.问题是,我仍然需要等到 BackgroundWorker 完成它的工作,这样我才能返回一个指示操作成功的布尔值.有一些方法可以解决这个问题,但从我的阅读来看,不得不等待 BackgroundWorker 完成其工作,这违背了使用它的初衷.那么,防止 UI 锁定的最佳方法是什么?
Thanks for the responses so far everybody. I've done some further reading, and I'm wondering if I'm going about this the right way. The reason I'm using a BackgroundWorker is to ensure that the UI remains responsive while I'm performing file operations. The issue is, I still need to wait until the BackgroundWorker has done its job so I can return a boolean indicating the success of the operation. There's ways to work around this, but from my reading, having to wait for a BackgroundWorker to complete its work is defeating the purpose of using it in the first place. So, what's the best way to go about preventing the UI from locking up?
推荐答案
好的,到目前为止做得很好.
OK, well done for getting so far.
让我们从第 1 点开始.
Lets start with point 1.
如果您使用多线程来提高 Windows 的性能表单应用程序,您必须确保调用您的以线程安全的方式进行控制.
对 Windows 窗体控件的访问本质上不是线程安全的.如果你有两个或多个线程操作控件的状态,它是可能会强制控件进入不一致的状态.
Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state.
因此,如您所见,您需要确保在更改控件的状态时,它是以线程安全的方式完成的.
So, as you can see, you need to ensure that when changing the state of a control, it is done in a threadsafe manner.
现在,属性 Control.InvokeRequired 检查您正在执行的代码是否在与最初创建控件的线程不同的线程上.
Now, the property Control.InvokeRequired checks whether the code you are executing is on a different thread to the one that originally created the control.
如果是,我们需要某种方式来调用该原始线程上的代码.
If it is, we need some way to call code on that original thread.
为此,您需要使用 控制.Invoke Method 在原线程上执行这样的代码.
For this reason you need to use Control.Invoke Method to execute such code on the original thread.
在拥有控件底层的线程上执行委托窗口句柄.
现在问题是,您需要告诉该线程它应该执行什么,这可以使用 委托.
Now the thing is, you need to tell that thread what it should be executing, and this is done using the delegate.
代表一个委托,它是一个数据结构,它引用一个静态方法或类实例及其实例方法类.
现在,我要推荐的最后一件事是你看看委托、匿名委托、匿名方法和 Lamda 表达式之间的区别.
Now, the last thing I would recommend is that you look at what the differences between Delegates, Anonymous Delegates, Anonymous Methods and Lamda expressions.
这篇关于VB.NET 代表和调用 - 有人可以向我解释这些吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!