根据Jon Skeet的说法,“您只能在具有单个目标调用的委托上调用BeginInvoke。”
为什么呢?真正的原因是什么?
注意:为了澄清(并且因为我犯了这个错误),我谈论的是委托上的BeginInvoke,而不是控件上的BeginInvoke。
为什么呢?真正的原因是什么?
注意:为了澄清(并且因为我犯了这个错误),我谈论的是委托上的BeginInvoke,而不是控件上的BeginInvoke。
给定任何委托类型,我们可以相当容易地编写一个类,该类将组合那种类型或派生类型的委托,并产生一个组合委托,该委托几乎可以做到 MulticastDelegate
可以做的一切事情,以及一些它不能做的事情。这种组合委托风格唯一无法做到的是通过 Delegate.Remove
将其子组件取出(因为该函数将把组合委托视为一个单元)。与 MulticastDelegate 不同,组合委托将能够包括派生委托类型,并且在只想要一个目标的地方也能正常工作。
在 vb.net 中,代码可能如下:
双动作类(DoubleAction) Private _Act1,_Act2 As Action(Of T) Private Sub New(ByVal Act1 As Action(Of T),ByVal Act2 As Action(Of T)) _Act1 = Act1 _Act2 = Act2 End Sub Private Sub Invoke(ByVal Param As T) _Act1(Param) _Act2(Param) End Sub Function Combine(ByVal Act1 As Action(Of T),ByVal Act2 As Action(Of T))As Action(Of T) Dim newAct As New DoubleAction(Of T)(Act1,Act2) Return AddressOf newAct.Invoke End Function End Class将其翻译成C#应该很简单。
这种组合委托的方法唯一的问题是需要为每个通用委托族支持编写样板代码(因为.NET不允许将委托用作通用类型参数)。
还有一种解决方法是在System.MulticastDelegate对象上调用BeginInvoke方法:
public class Program{
public delegate void SayHello();
public void SayHelloAndWait(){
Console.WriteLine("HELLO..");
System.Threading.Thread.Sleep(5000);
Console.WriteLine("..WORLD!");
}
public void SayHi(){
Console.WriteLine("Hi world!");
}
public void Run(){
SayHello helloMethods;
helloMethods = SayHelloAndWait;
helloMethods += SayHi;
foreach(SayHello hello in helloMethods.GetInvocationList())
hello.BeginInvoke(null,null);
}
public static void Main(String[] args){
new Program().Run();
Console.Read();
}
}