多线程,返回状态的问题

Hotus 2016-02-18 12:43:50
把一个过程封装到类里面

Public Class TestCls
Public Event GetResult(ByVal Num As Integer)

Public Sub ReturnResult(ByVal Num As Integer)
RaiseEvent GetResult(Num)
End Sub

Public Sub TestSub
RetrunResult(100)
End Sub
End Class

在窗口里面
Private WithEvents OBJ As TestCls

th1 = New Thread(New ThreadStart(AddressOf OBJ.TestSub

Private Sub obj_GetResult(ByVal Num As Integer) Handles obj.GetResult
可以通过这个返回一直值来判断状态
End Sub

如果我现在要同时创建N个不固定的线程,WithEvents不支持数组,用 dim obj(999) as TestCls的话
Private Sub obj_GetResult(ByVal Num As Integer) Handles obj.GetResult
End Sub
就不能使用这个获取到返回的值了,有什么其他办法可以在窗口中获取到在线程中运行的过程返回的值吗?
...全文
251 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Hotus 2016-02-20
  • 打赏
  • 举报
回复
用类,主要是因为在线程中要传递参数进去,可能同时会创建N个线程,执行相同的过程,只是处理的参数不一样 我想让线程里面的过程执行完后,发出个什么通知,让主线程知道就行了 我去看看 addhander addressof怎么用,以前一直用的VB,没接触过多线程,.NET的多线程确实是方便
Hotus 2016-02-20
  • 打赏
  • 举报
回复
谢谢,我先消化下
  • 打赏
  • 举报
回复
嗯,PLinq 的 result 是自动等待所有结果都返回到主线程才完成的(这可能是它不如上面的 QueueUserWorkItem 的地方),所以其实我上面的例子多余使用了 BeginInvoke 函数。 可以写为
Imports System.Threading

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim query = From i In Enumerable.Range(0, 20).AsParallel    '注意,关键是 .AsParallel
                    Select TestCls.TestSub(i)
        For Each result In query
            Me.ListBox1.Items.Add(result)
        Next
    End Sub
End Class

Public Class TestCls
    Shared rnd As New Random

    Public Shared Function TestSub(i As Integer) As String
        Thread.Sleep(rnd.Next(2000))
        Return i & "__threadId=" & Thread.CurrentThread.ManagedThreadId & ", 返回值=" & 100
    End Function
End Class
  • 打赏
  • 举报
回复
这个例子,是基于你的 class 的架构设计而编写的。 假设方法本身直接就有返回值,但是你希望在子线程中调用方法,那么其实本身是很简单的。例如
Imports System.Threading

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim query = From i In Enumerable.Range(0, 20).AsParallel    '注意,关键是 .AsParallel
                    Select TestCls.TestSub(i)
        For Each result In query
            Me.BeginInvoke(Sub()
                               Me.ListBox1.Items.Add(result)
                           End Sub)
        Next
    End Sub
End Class

Public Class TestCls
    Shared rnd As New Random

    Public Shared Function TestSub(i As Integer) As String
        Thread.Sleep(rnd.Next(2000))
        Return i & "__threadId=" & Thread.CurrentThread.ManagedThreadId & ", 返回值=" & 100
    End Function
End Class
这就像 #3 楼说的,使用 PLinq 可以轻松地用一个 .AsParallel 搞定多线程,用不着你写复杂的代码。
  • 打赏
  • 举报
回复
给你写一个例子。 假设线程执行完毕,要把结果写到 Form 中的一个 ListBox 列表框
Imports System.Threading

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim lst As New List(Of TestCls)
        For i = 0 To 20
            Dim obj As New TestCls With {.i = i}
            AddHandler obj.GetResult, Sub(n As Integer)     '显示结果。它在子线程中运行
                                          Dim 线程id = Thread.CurrentThread.ManagedThreadId
                                          Me.BeginInvoke(Sub()
                                                             Me.ListBox1.Items.Add(obj.i & "__threadId=" & 线程id & ", 返回值=" & n)
                                                         End Sub)
                                      End Sub
            lst.Add(obj)
        Next
        For Each j In lst
            ThreadPool.QueueUserWorkItem(Sub()
                                             j.TestSub()
                                         End Sub)
        Next
    End Sub
End Class

Public Class TestCls
    Public i As Integer

    Public Event GetResult(ByVal Num As Integer)

    Public Sub ReturnResult(ByVal Num As Integer)
        RaiseEvent GetResult(Num)
    End Sub

    Shared rnd As New Random

    Public Sub TestSub()
        Thread.Sleep(rnd.Next(2000))
        ReturnResult(100)
    End Sub
End Class
你可以看到,这里创建了20个 TestCls 对象,分别设置了它们的回调事件处理委托方法。然后在一个 for each 循环中,分别注册给系统线程池,以子线程来调用每一个对象的 TestSub 方法。 在事件抛出时,是先注册的事件处理方法在主线程的窗体子控件打印了:输入值、线程id、返回值。
qbilbo 2016-02-19
  • 打赏
  • 举报
回复
一,类的构造函数里传入一个唯一标识,这样事件参数里就能定义一个表示唯一标识的参数。 二,其实.net中当你要启动线程时,基本上用不到用Thread类,有各种更简单方便的方法。 比如你说的这种情况,可以这样:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Parallel.For(0, 5, Sub(n) MsgBox(String.Format("1 + {0} ={1}", n, Add(1, n))))
End Sub
Private Function Add(ByVal x As Integer, y As Integer) As Integer
        Thread.Sleep(y * 1000) '模拟长时间运算
        Return x + y
End Function
zhh0000zhh 2016-02-19
  • 打赏
  • 举报
回复
addhander obj.GetResult,addressof obj_GetResult
Hotus 2016-02-18
  • 打赏
  • 举报
回复
我现在是在类里面添加一个属性来存放,窗体里面再用timer来查询,这样应该是效率最低下的方法了

16,555

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧