VB.NET代表和调用 - 可以有人向我解释这些吗? [英] VB.NET Delegates and Invoke - can somebody explain these to me?

查看:119
本文介绍了VB.NET代表和调用 - 可以有人向我解释这些吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是线程世界的新手,但是我正在开发的一个应用程序的几个方面要求我使用BackgroundWorker控件来防止在进行某些文件操作时将UI冻结。



我要做的是从BackgroundWorker中更新几个表单标签。在我很快发现我无法访问在同一个线程中未创建的控件之前,从未使用过这样的操作,所以在进行了一些研究后,我实现了以下代码,似乎使一切正常工作:

 私人委托Sub DelegateUpdateStatus(ByVal statusText As String,ByRef currentFile As String)

Private Sub UpdateStatus(ByVal statusText As String,ByVal currentFile As String)

如果InvokeRequired然后
调用(Sub()LblStatus.Text = statusText)
调用(Sub()LblCurrentFile.Text = currentFile)
Else
LblStatus.Text = statusText
LblCurrentFile.Text = currentFile
如果

End Sub
/ pre>

虽然,我不了解这段代码正在做什么,或者为什么需要。



我已经做了一些研究,但是我没有做任何真正的工作,这种事情,最关键我已经阅读了一些先前的知识。



我想要了解的三个主要事项:




  • 为什么这个代码是必需的(如何,为什么无法直接从BackgroundWorker访问控件)

  • 代理是什么,当需要使用它时

  • Invoke方法所做的是什么,我正在使用InvokeRequired进行检查



如上所述,线程仍然是一个外国的概念,所以任何简单的英语答案将是非常有帮助的 - 谢谢!



编辑:感谢您的到目前为止所有人的回应。我已经做了一些进一步的阅读,我想知道我是否正确的方式。我正在使用BackgroundWorker的原因是确保在执行文件操作时UI保持响应。问题是,我仍然需要等到BackgroundWorker完成其工作,所以我可以返回一个布尔值,表示操作的成功。有办法解决这个问题,但从我的阅读,不得不等待一个BackgroundWorker来完成它的工作是打败了首先使用它的目的。那么,阻止UI锁定的最好方法是什么?

解决方案

好的,做得很好。



从点1开始。



如何:对Windows窗体控件进行线程安全调用


如果您使用多线程来提高Windows
表单应用程序的性能,则必须确保在线程中调用
控件安全的方式。



访问Windows窗体控件本身不是线程安全的。如果
有两个或多个线程操纵控件的状态,则可以将
强制控件置于不一致状态。


所以,您可以看到,您需要确保在更改控件的状态时,以线程安全的方式完成。



现在,属性 Control.InvokeRequired 检查您正在执行的代码是否与最初创建控件的代码不同。



如果是,我们需要一些方法来调用该原始代码线程。



因此,您需要使用 Control.Invoke方法在原始线程上执行此类代码。


在拥有该控件的线程上执行一个委托我的底层
窗口句柄。


现在的事情是,你需要告诉线程应该执行什么,这是使用委托完成的。


表示一个委托,它是一个引用
静态方法或类实例的数据结构,而
的实例方法类别。


现在,我建议的最后一件事是你看看代理,匿名代理,匿名方法和Lamda表达式。


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.

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:

  • Why this code is required (as in, why the controls can't be accessed directly from the BackgroundWorker)
  • What a delegate is, and when the use of it is required
  • What the Invoke method does, and what I'm checking for with InvokeRequired

As said, threading is still quite a foreign concept, so any answers in plain English would be really helpful - thanks!

EDIT: 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.

Lets start with point 1.

From How to: Make Thread-Safe Calls to Windows Forms Controls

If you use multithreading to improve the performance of your Windows Forms applications, you must make sure that you make calls to your controls in a thread-safe way.

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.

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.

For this reason you need to use Control.Invoke Method to execute such code on the original thread.

Executes a delegate on the thread that owns the control's underlying window handle.

Now the thing is, you need to tell that thread what it should be executing, and this is done using the delegate.

Represents a delegate, which is a data structure that refers to a static method or to a class instance and an instance method of that class.

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代表和调用 - 可以有人向我解释这些吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆