【异步编程】异步执行,获取返回值

苦苦的潜行者 2011-11-01 10:42:31
上次在看线程时,知道了委托.好不容易搞明白了委托怎么写,
原先的问题http://topic.csdn.net/u/20111019/17/ac098c48-ed25-4e1f-acd0-ec192ca44eac.html
又想知道线程什么时候结束,或者我想知道我授予线程的过程执行的怎么样了.
如是到网上查,omg,异步..回调执行,
我找了一个一例子,然后照葫芦画瓢,但是得不到正确的结果.

//我的以下是想实现将form的text修改一下,然后线程执行完毕后,提示我一下.

Imports System.Threading
Imports System.Runtime.Remoting.Messaging
Public Class Form1
Private Delegate Sub myDelegate(ByVal myString As String) '自定义一个委托
Dim MyThread As System.Threading.Thread
Private Sub SetWindowText(ByVal myString As String) '与委托相同签名的函数或过程
Me.Text = myString
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MyThread = New System.Threading.Thread(AddressOf sum)
MyThread.Start()
End Sub

Private Sub sum()
Dim sum As Single
sum = Rnd()
Dim b As myDelegate = New myDelegate(AddressOf SetWindowText)
'Me.Invoke(New myDelegate(AddressOf SetWindowText), sum.ToString) '委托的调用
'Me.Invoke(b, sum.ToString)
'这儿将me.invoke替换为下面的BeginInvoke又会导致非法调用控件啊.
Dim myar As IAsyncResult = b.BeginInvoke(sum.ToString, New AsyncCallback(AddressOf CallBackThread), "执行完毕!")
End Sub


Private Sub CallBackThread(ByVal myar As IAsyncResult)
msgbox( "当前线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)

Dim ar As AsyncResult = CType(myar, AsyncResult)
Dim b As myDelegate = CType(ar.AsyncDelegate, myDelegate)
b.EndInvoke(myar)
MsgBox(myar.AsyncState.ToString)
End Sub
End Class


请教在这一方面有兴趣和大神.
...全文
579 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
积善成魔 2011-11-03
  • 打赏
  • 举报
回复
Private Delegate Sub myDelegate(ByVal myString As String)
Dim MyThread As System.Threading.Thread

Private Sub SetWindowText(ByVal myString As String)
Debug.Print("SetWindowText线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
MyThread = New System.Threading.Thread(AddressOf sum)
MyThread.Start()
Debug.Print("Button线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub

Private Sub sum()
Dim sum As Single
sum = Rnd()
Dim b As myDelegate = New myDelegate(AddressOf SetWindowText)
Dim myar As IAsyncResult = b.BeginInvoke(sum.ToString, New AsyncCallback(AddressOf CallBackThread), "执行完毕!")
Debug.Print("sum线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub

Private Sub CallBackThread(ByVal myar As IAsyncResult)
Debug.Print("CallBackThread线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub

会看到这段代码产生了三个线程。
阿非 2011-11-03
  • 打赏
  • 举报
回复

Private Delegate Sub BeginInvokeDelegate()

Private Sub SetTextBoxText()
lbl2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
End Sub

Private Sub ThreadMethod()
Thread.Sleep(3000)
Me.BeginInvoke(New BeginInvokeDelegate(AddressOf SetTextBoxText))
End Sub

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim t As New Thread(AddressOf ThreadMethod)
t.Start()
lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
End Sub

lbl1 和 lbl2 都是 Label
积善成魔 2011-11-03
  • 打赏
  • 举报
回复
再补充一下

线程可以理解成一个独立的过程(SUB)。

过程结束(END SUB)时,也意味着线程结束。

在过程结束之前,调用的委托,有可能委托代码执行时,线程已经结束。

Invoke跟BeginInvoke是两个概念,Invoke由控件继承表示A线程让B线程上执行某段代码

BeginInvoke则表示在当前线程A上开启一个新线程B进行异步操作。

LZ的代码在A线程上启动了BeginInvoke,于是开启了线程B,当线程B返回EndInvoke时,直接调用了线程C上的控件,于是就报错了。

苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 sandy945 的回复:]

引用 18 楼 xiaolinyouni 的回复:
引用 17 楼 sandy945 的回复:

VB.NET code

Private Delegate Sub Action()
Private Delegate Sub BeginInvokeDelegate(myString As String, action As Action)

Private Sub SetText……
[/Quote]

哎呀,我跪接,太有价值了/多谢
阿非 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 xiaolinyouni 的回复:]
引用 17 楼 sandy945 的回复:

VB.NET code

Private Delegate Sub Action()
Private Delegate Sub BeginInvokeDelegate(myString As String, action As Action)

Private Sub SetTextBoxText(myString As String, ……
[/Quote]
http://www.cnblogs.com/smartls/archive/2011/03/08/1977276.html
http://www.cnblogs.com/smartls/archive/2011/04/08/2008981.html#2104297
http://www.cnblogs.com/c2303191/articles/826571.html
http://www.cnblogs.com/conger/archive/2011/05/24/2055113.html
积善成魔 2011-11-03
  • 打赏
  • 举报
回复
Control.BeginInvoke
可以理解为,新开启一个线程A,然后A调用Control.Invoke 等于是省掉一个Thread声明

Delegate.BeginInvoke可以理解为新开启一个线程A 在A上面运行委托的过程,也相当于省掉一个Thread
声明

Private Delegate Sub myDelegate(ByRef myString As String)
Dim MyThread As System.Threading.Thread

Private Sub SetWindowText(ByRef Start As String)
Dim i As Long
Dim n As Long
n = CLng(Start)
For i = n To n + 200
i += 1
Threading.Thread.Sleep(10)
Next
Start = i
Debug.Print("SetWindowText计算结果:" & i)
Debug.Print("SetWindowText线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
MyThread = New System.Threading.Thread(AddressOf sum)
MyThread.Start()
Debug.Print("Button线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub

Private Sub sum()
Dim n As Integer
Dim b As myDelegate = New myDelegate(AddressOf SetWindowText)
Dim myar As IAsyncResult = b.BeginInvoke(n, New AsyncCallback(AddressOf CallBackThread), "执行结束!")
Threading.Thread.Sleep(10)
If myar.IsCompleted Then '判断是否完成
Debug.Print("委托线程结束")
Else
Debug.Print("委托线程还在继续")
End If
myar.AsyncWaitHandle.WaitOne(100) '另外的线程等待一百毫秒
Debug.Print("sum线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
'Dim s As String = ""
'b.EndInvoke(s, myar)'等待直到返回
'Debug.Print("得到函数的计算返回值" & s)
End Sub

Private Sub CallBackThread(ByVal myar As IAsyncResult)

Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = myar
Dim b As myDelegate = CType(ar.AsyncDelegate, myDelegate)
Dim s As String = ""
b.EndInvoke(s, myar)
Debug.Print("CallBackThread得到函数的计算返回值" & s)
Debug.Print("CallBackThread返回:" & myar.AsyncState)
Debug.Print("CallBackThread线程是:" & System.Threading.Thread.CurrentThread.ManagedThreadId)
End Sub
chen40252540 2011-11-03
  • 打赏
  • 举报
回复
LZ这个有涉及到跨线程调用控件!
Control.CheckForIllegalCrossThreadCalls = False
LZ在线程调用前加上这句试试看!
记得线程走完要弄回来,毕竟支持跨线程调用控件这样不好
苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 sandy945 的回复:]

VB.NET code

Private Delegate Sub Action()
Private Delegate Sub BeginInvokeDelegate(myString As String, action As Action)

Private Sub SetTextBoxText(myString As String, action As Action)
……
[/Quote]


哥,我泪流满面,确实是这样.
我再去查查Control的invoke和begininvoke还有delegate的invoke和begininvoke的知识.
你要是有什么推荐的知识点也给我说下哈/
多谢,哦,对了我加你好友了,敬请允许.
阿非 2011-11-03
  • 打赏
  • 举报
回复

Private Delegate Sub Action()
Private Delegate Sub BeginInvokeDelegate(myString As String, action As Action)

Private Sub SetTextBoxText(myString As String, action As Action)
lbl2.Text = String.Format("我是传参:{0},当前时间:{1}", myString, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
action()
End Sub

Private Sub ThreadMethod(myString As String)
Thread.Sleep(3000)
Me.BeginInvoke(New BeginInvokeDelegate(AddressOf SetTextBoxText), myString, New Action(AddressOf CallBackSub))
End Sub

Private Sub CallBackSub()
MessageBox.Show("我是CallBack")
End Sub


Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim t As New Thread(AddressOf ThreadMethod)
t.Start("传参")
lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
End Sub

苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 sandy945 的回复:]

首先 你要明白 Control.BeginInvoke 与 Delegate.BeginInvoke 不是一个概念
[/Quote]

我去搜搜,
苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 haoting987 的回复:]

Private Delegate Sub myDelegate(ByVal myString As String)
Dim MyThread As System.Threading.Thread

Private Sub SetWindowText(ByVal myString As String)
Debug.Print("SetWindowTe……
[/Quote]

我居然愣是找不到debug窗口在哪...我是vs2008
阿非 2011-11-03
  • 打赏
  • 举报
回复
首先 你要明白 Control.BeginInvoke 与 Delegate.BeginInvoke 不是一个概念
苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 sandy945 的回复:]

VB.NET code

Private Delegate Sub BeginInvokeDelegate()

Private Sub SetTextBoxText()
lbl2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
End Sub

Private Sub ThreadMethod()……
[/Quote]

嗯,收到了,确实可以.原来可以这么写.
//不要嫌我啰嗦,虽然你给了可行的代码,但是我还得用我自己的理解去接受,理解了以后就不会死套大神的代码了,是不?
还有一点啊,
我的代码用你的方法改为如下
    Private Delegate Sub myDelegate(ByVal myString As String) '自定义一个委托
Dim MyThread As System.Threading.Thread
Private Sub SetWindowText(ByVal myString As String) '与委托相同签名的函数或过程
Me.Text = myString
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MyThread = New System.Threading.Thread(AddressOf sum)
MyThread.Start()
End Sub

Private Sub sum()
Dim sum As Single
sum = Rnd()
Me.BeginInvoke(New myDelegate(AddressOf SetWindowText), sum.ToString)
End Sub

虽然你给的代码确实实现了操作控件,但是除了我观察控件,我没法知道它执行的情况,也就是不能callback了,是吧?.....我是不是想多了,你批评我吧.
阿非 2011-11-03
  • 打赏
  • 举报
回复
醍醐灌顶?
苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 haoting987 的回复:]

再补充一下

线程可以理解成一个独立的过程(SUB)。

过程结束(END SUB)时,也意味着线程结束。

在过程结束之前,调用的委托,有可能委托代码执行时,线程已经结束。

Invoke跟BeginInvoke是两个概念,Invoke由控件继承表示A线程让B线程上执行某段代码

BeginInvoke则表示在当前线程A上开启一个新线程B进行异步操作。

LZ的代码在A……
[/Quote]

大有醍醐灌顶的感觉啊.
//haoting978可否给我讲解一下,这一句
Dim myar As IAsyncResult = b.BeginInvoke(sum.ToString, New AsyncCallback(AddressOf CallBackThread), "执行完毕!")
的执行流程.还有我对有参和无参的的sub(作为线程在使用的时候)还是比较含糊.
阿非 2011-11-03
  • 打赏
  • 举报
回复
不是给你写示例了么?
苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 haoting987 的回复:]

委托的意思是 在A线程中调用B线程的消息循环执行某段代码。

线程可以理解成一个独立的过程(SUB)。

当调用委托时,委托部分的代码将在另一线程中执行。

线程状态可以直接调用Thread的属性来查询。

线程中的代码执行的位置,只能用一些公共状态值来判断。
[/Quote]

嗯嗯.
小弟听着,你继续讲,很朴实的说.
苦苦的潜行者 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 andywongz 的回复:]
写多线程的代码,要注意的是不要在多个线程里调用同一个控件,否则就会造成非法调用控件

一个良好的风格应该是,有且只有一个主线程,这个主线程负责界面控制以及调用其他线程

而其他的线程,最好都只进行纯数据运算,而不要涉及与界面相关的操作

而主线程与其他线程之间的通信,可以用几个线程都能访问的公共变量来执行,这是比较稳妥的办法。
[/Quote]

嗯嗯,我也觉得如果把
Private Sub SetWindowText(ByVal myString As String) '与委托相同签名的函数或过程
Me.Text = myString
End Sub
中的Me.text=myString换成一个公共变量,不涉及控件操作,就不会报错.
还有你说的保证有且只有一个主线程,主线程与其他线程之间的通信,可以用几个线程都能访问的公共变量来执行很受用.
我在整的时候确实被葫芦的代码牵着走,也不太明白什么意思,而且对什么是主线程和其他线程没有明确的概念,可否帮我分析一下.




,使.
,.
老龙友 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用楼主 xiaolinyouni 的回复:]
上次在看线程时,知道了委托.好不容易搞明白了委托怎么写,
原先的问题http://topic.csdn.net/u/20111019/17/ac098c48-ed25-4e1f-acd0-ec192ca44eac.html
又想知道线程什么时候结束,或者我想知道我授予线程的过程执行的怎么样了.
如是到网上查,omg,异步..回调执行,
我找了一个一例子,然后照葫芦画瓢,但是得不到正确的结果……
[/Quote]

写多线程的代码,要注意的是不要在多个线程里调用同一个控件,否则就会造成非法调用控件

一个良好的风格应该是,有且只有一个主线程,这个主线程负责界面控制以及调用其他线程

而其他的线程,最好都只进行纯数据运算,而不要涉及与界面相关的操作

而主线程与其他线程之间的通信,可以用几个线程都能访问的公共变量来执行,这是比较稳妥的办法。
积善成魔 2011-11-02
  • 打赏
  • 举报
回复
委托的意思是 在A线程中调用B线程的消息循环执行某段代码。

线程可以理解成一个独立的过程(SUB)。

当调用委托时,委托部分的代码将在另一线程中执行。

线程状态可以直接调用Thread的属性来查询。

线程中的代码执行的位置,只能用一些公共状态值来判断。

加载更多回复(1)

16,557

社区成员

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

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