VB.net,调用,委托和线程.无法弄清楚如何跨课程使用它们 [英] VB.net, Invoke, delegates, and threading. Can't figure out how to use them across classes

查看:264
本文介绍了VB.net,调用,委托和线程.无法弄清楚如何跨课程使用它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长话短说,我在尝试弄清楚如何在使用线程时如何使用调用和/或委托来从单独的类中更新用户窗体时遇到了麻烦.我敢肯定,对于有更多经验的人来说,这是愚蠢而显而易见的.我知道可能需要委托,但是我的所有努力似乎仅在从主线程调用它时才起作用.我已经在互联网上闲逛了半天,但有一些我没有得到.

Long story short, I'm having a hell of a time trying to figure out how to use invoke and/or delegates to update the userform from a separate class when using threading. I'm quite sure it's something silly and obvious to someone with more experience. I know a delegate is probably required, but all my efforts seem to only work when it's being called from main thread. I've been looking around the internet for half the day, and there's just something I'm not getting.

这里有一些伪代码作为示例:

Here's some pseudo-code as an example:

此选项有效:

Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim t1 As New Threading.Thread(AddressOf Count)

    t1.IsBackground = True

    t1.Start(100)
End Sub
Private Sub Count(ByVal Max As Object)
    If TypeOf Max Is Integer Then
        Count(CInt(Max))
    End If
End Sub


Private Sub SetLabelText(ByVal text As String)
    If Label1.InvokeRequired Then
        Label1.Invoke(New Action(Of String)(AddressOf SetLabelText), text)
    Else
        Label1.Text = text

    End If
End Sub

Private Sub Count(ByVal Max As Integer)
    For i = 1 To Max
        SetLabelText(CStr(i))
        Threading.Thread.Sleep(200)
    Next
End Sub
End Class

虽然(我的1000项稍有不同的变化的努力之一)却没有.实际上,在这个示例中,我只是尝试将一个子对象分离到自己的类中,但是其他方面与我可以做到的相同:

While this (one of my 1000 efforts of slightly different variation) does not. Practically speaking, I just tried to separate one of the subs into its own class for this example, but it's otherwise the same as I could make it:

Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim t1 As New Threading.Thread(AddressOf Count)
    t1.Start(100)

End Sub
Private Sub Count(ByVal Max As Object)
    If TypeOf Max Is Integer Then
        Dim class2 As New class2
        class2.Count(CInt(Max))
    End If
End Sub

Private Delegate Sub SetTextBoxTextInvoker(text As String)
Sub SetLabelText(ByVal text As String)
'or me.label1, form1.label1 or anything else I can try!
    If Me.InvokeRequired Then
        Me.Invoke(New SetTextBoxTextInvoker(AddressOf SetLabelText), _
               text)
    Else
        Me.Label1.Text = text
    End If
End Sub
End Class

Public Class class2
Sub Count(ByVal Max As Integer)
    For i = 1 To Max
        form1.SetLabelText(CStr(i))
        Threading.Thread.Sleep(200)
    Next
End Sub
End Class

据我所知,似乎在Sub"SetLabelText"中所需的if语句if永远不会被触发.我最好的猜测是,在检查invokerequired参数时,我没有正确地引用用户表单?还是我需要向代表提供其他信息?我只是对弄乱我可能弄错的数百万个小变量而感到沮丧.预先感谢您可以提供的任何帮助,如果您需要更多信息,请告诉我.

From what I can tell, it appears that the if statement for invokerequired in the Sub "SetLabelText" never gets triggered. My best guess is that I'm not referring to the userform correctly when checking for the invokerequired parameter? Or I need to feed something else to the delegate? I'm just getting frustrated with messing around with the million little variables I might be getting wrong. Thanks in advance for any help you can provide and let me know if you need more info.

推荐答案

我不确定我是否理解您要执行的操作,但是在您的代码的基础上,您可以安全地设置标签(线程安全")通过使用以下代码:

I'm not certain I understand what you are trying to do, but building upon your code, you can set the label safely ("thread-safely") by using the following code:

Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim t1 As New Threading.Thread(AddressOf Count)

        t1.IsBackground = True

        t1.Start(100)
    End Sub

    Private Sub Count(ByVal Max As Object)
        If TypeOf Max Is Integer Then
            Dim class2 As New Class2

            class2.Count(CInt(Max), AddressOf SetLabelText)
        End If
    End Sub

    Private Sub SetLabelText(ByVal text As String)
        If Label1.InvokeRequired Then
            Label1.Invoke(New SetText(AddressOf SetLabelText), text)
        Else
            Label1.Text = text
        End If
    End Sub
End Class

Public Class Class2
    Sub Count(ByVal Max As Integer, SetTextMethod As SetText)
        For i = 1 To Max
            SetTextMethod.Invoke((CStr(i)))

            Threading.Thread.Sleep(200)
        Next
    End Sub
End Class

Public Delegate Sub SetText(text As String)

我创建了一个名为"SetText"的代表;当表单在您的类中调用count函数时,您可以传递引用SetLabelText方法的委托的实例.然后,在该方法中,您可以直接或间接通过Invoke以及新的委托实例安全地设置标签文本.

I created a Delegate called "SetText"; when the form calls the count function in your class, you can pass an instance of the delegate that references the SetLabelText method. Within that method you can then safely set the label text either directly or indirectly via Invoke along with a new instance of the delegate.

您绝对不想做的是从您的类中引用您的表单(即"form1.SetLabelText(CStr(i))");随着项目规模的增长和需求的变化,这可能会造成一场真正的噩梦!

Something you definitely don't want to do is reference your form from your class(i.e. "form1.SetLabelText(CStr(i))"); that can create a real nightmare as the project grows in size and requirements change!

如果我误解了您的问题或未能正确回答,请回发.

If I've misunderstood your question or not answered it properly, please do post back.

这篇关于VB.net,调用,委托和线程.无法弄清楚如何跨课程使用它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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