可以在选定全部子节点前,发送一个变量给全部子节点(有个tag属性可以利用),告诉它们不应该执行某事件(if语句)。
创新互联公司是一家专注于成都网站建设、成都做网站与策划设计,剑川网站建设哪家好?创新互联公司做网站,专注于网站建设10余年,网设计领域的专业建站公司;建站业务涵盖:剑川等地区。剑川做网站价格咨询:18980820575
委托是可用于调用其他对象方法的对象。它们有时被称为类型安全函数指针,因为它们与其他编程语言中所使用的函数指针相似。但不同于函数指针,Visual Basic .NET 委托是基于 System.Delegate 类的引用类型,它可以引用共享方法 —无需特定的类实例即可调用的方法和实例方法。
委托在调用过程和被调用过程需要媒介的情况下是很有用的。例如,您可能想让一个引发事件的对象能够在不同的环境下调用不同的事件处理程序。不幸的是,引发事件的对象无法提前知道处理特定事件的事件处理程序。Visual Basic .NET 通过在使用 AddHandler 语句时创建委托,可让您动态地将事件处理程序与事件关联。在运行时,委托将各种调用转发到相应的事件处理程序。
尽管可以创建自己的委托,但在大多数情况下,Visual Basic .NET 为您创建委托并提供具体信息。例如,Event 语句将名为 EventNameEventHandler 的委托类隐式定义为 Event 语句所在类的嵌套类,且其签字与该事件相同。AddressOf 语句则隐式创建委托的实例。例如,以下两行代码是等效的:
AddHandler Button1.Click, AddressOf Me.Button1_Click
' AddHandler 指向引发事件的对象,AddressOf则确定该事件对象所要调用的事件处理程序
'上述行为又可以称为 监 视
AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)。
委托,Delegate
就是让你处于这个线程里时,委托另一个线程去执行一些动作
我简单举一个写richtextbox的例子:
////////////////////////////////////////////
'创建一个名为 MySubDelegate 的委托。
Delegate Sub MySubDelegate(ByVal txt As String)
'写信息到富文本主窗口
Private Sub txtW(ByVal txt As String)
Dim msgd As New MySubDelegate(AddressOf Me.txtW1)
Dim arg(0) As Object
arg(0) = txt
Me.Invoke(msgd, arg)
End Sub
'委托指向
Private Sub txtW1(ByVal txt As String)
Me.RichTextBox1.AppendText(txt)
End Sub
/////////////////////
这样,你在多线程应用时,在其他线程里用txtW(str)来写richtextbox,就不会产生错误了。不然,直接垮线程写richtextbox,可能会出现和UI线程的冲突。
所谓的委托(Delegate)实际上就是和C/C++里面的函数指针差不多,只是增强了类型检查等其它健壮性方面的内容。异步调用的回调函数有格式要求,所谓格式要求就是参数数量及类型顺序的要求,具体是什么样的你要看文档了。一般.NET Framework里面都是AsyncCallBack。
所谓异步编程,就是说你要求做某样事情,但是在完成这件事之前,我能接着做下一件事,而当这件事情完成之后,能够有一种机制通知我完成了。相反,在完成之前一直等待,直到完成了才能进行下一步操作,叫做同步。一般来说,我们平常写的程序都是“同步”,或者成为“顺序执行”更加贴切,而“异步”则可以说是“乱序执行”的。
可以看到,同步的代码非常好写,因为我们可以预测执行的顺序和情况。而异步就不是很好写了,因为无法得知完成的时候我正在做什么、做到什么程度。过去写这些代码是比较麻烦的,实现的办法就是自己建立一个处理异步事物的线程,然后在这个线程和主线程之间建立联系。而现在这个过程大部分已经被系统封装起来了,你只要调用BeginXXX,系统就会为你自动建立一个新的线程处理这个事情,当前线程不阻塞,可以马上进行下一项操作,于是就实现了“异步”了。但是从前面我讲道的你就应该知道,开始异步操作并没有完事,还需要能够得知操作完成,并能够进行相应的处理。于是你在调用BeginXXX的时候就需要传递一个回调函数,在.NET里是以委托的方式传递的。回调函数的意思就是“回过头来调用你”,或者说A调用B并且传递函数C的地址,于是B在指定的情况下调用A指定的函数C。现在就应该明白这个回调函数在BeginXXX中的作用就是,当你指定的事情做完之后将会调用这个回调函数。
在这个回调函数里面,我们就可以进行一些后续的工作,例如接着进行性质相同的工作,或者相应的处理。在这里,我们也许向知道刚才那件事情执行的情况和结果,这个时候我们就可以通过EndXXX来获得这些东西。说到这里,结合上面说到的AsyncCallBack以及随便哪个BeginXXX,我们可能会对下列两个东西感到困惑:
IAsyncResult
stateObject
首先说IAsyncResult,这个是一个接口,你在回调函数中通过参数获得的对象具体是什么类型的一般我们不需要关心,我们只需要依照这个接口的定义进行访问就可以了。简单点说,这个接口规定了顺利完成异步操作所需信息的最小集合。一般来说,我们需要通过这个参数(ar)来识别异步操作。比如说,你在一瞬间发起一百个“从不同的网络连接获取数据”的异步请求,当某一个请求被完成的时候,如何判断是那个请求被完成呢?就是依靠回调函数的参数ar。实际上你一般是不需要参与判断的,你只要将这个ar传递给EndXXX就可以了,EndXXX会根据这个ar自行判断的。需要注意的是,这个ar就是你调用BeginXXX的时候的返回值,可以说是一个存根,如果你需要在完成操作前终止他,也可以通过将这个存根传递给EndXXX,EndXXX就会根据情况终止操作。(IAsyncResult里面的IsCompleted提供了是否已经完成的判断,EndXXX就是根据这个值决定是否有必要终止。当然,你不需要关心他。)
接下来我们看看stateObject,这个东西被称为状态对象。于是大家就可能奇怪了:那个ar不也是状态吗?实际上stateObject是一个留给用户使用的东西,BeginXXX/EndXXX根本就不使用。这个stateObject会被装到ar的AsyncState里面,也就是说这个stateObject可以随时通过访问存根(BeginXXX的返回值)或者回调函数里的ar得到,你完全没必要额外的保存到什么地方,更不需要费神的去考虑如何和你的某个异步操作对应起来。说了半天,这个东西有什么用呢?你想怎么用就怎么用呗,发挥一下你的想象力。比如说,你可以保存这是第几次操作,或者在多个异步操作之间要同步的时候可以作为信号旗,再或者直接是操作这个异步操作的对象(x.BeginXXX的时候将x传递到stateObject参数上)。
第一种用法有点多余,第二种用法有点复杂,第三种我用得最多。因为你很可能在协一个服务端,而服务段必须能够响应多个客户端,这决定了必须用异步。同时,对于多个客户端必然有多个对象,例如网络连接的时候可能是Socket。而实际上处理的方法或者协议是和具体哪个客户端没有关联的,因此我们只需要一套处理程序就够了。这个时候第三种用法就很有用处,我们完全可以把代码写成这样:
Sub DataReceived(ByVal ar As IAsyncResult)
ar.AsyncState.EndReceive(ar)
ar.AsyncState.BeginReceive(... , ar.AsyncState)
End Sub
这样就不需要额外的数据结构去记录有那些正在活动的对象了。
售后响应及时
7×24小时客服热线数据备份
更安全、更高效、更稳定价格公道精准
项目经理精准报价不弄虚作假合作无风险
重合同讲信誉,无效全额退款