我想BackgroundWorker
在运行时更改附加到 a 的委托。像下面这样的东西会起作用吗?
DoWorkEvenHandler dweh = new DoWorkEventHandler(method1);
backgroundworker.DoWork += dweh;
并在稍后DoWork
通过重新分配引用来更改关联的委托dweh
:
dweh = new DoWorkEventHandler(method2);
我想BackgroundWorker
在运行时更改附加到 a 的委托。像下面这样的东西会起作用吗?
DoWorkEvenHandler dweh = new DoWorkEventHandler(method1);
backgroundworker.DoWork += dweh;
并在稍后DoWork
通过重新分配引用来更改关联的委托dweh
:
dweh = new DoWorkEventHandler(method2);
不,您不能将委托“分配”给事件处理程序。处理程序通过将它们添加到内部用于表示事件的底层委托的调用列表来附加到事件。这是设计使然!
不,您不能通过更改以前用于附加事件处理程序的引用所指向的对象来更改处理程序;部分原因是委托是不可变的,部分原因是您只是将引用更改为指向其他内容,而不是真正更改您要完成的事件处理程序。
为了更改委托,您必须首先删除以前的委托:
backgroundworker.DoWork -= dweh;
然后通过将其添加为事件的处理程序来分配一个新的:
backgroundworker.DoWork += new DoWorkEventHandler(method2);
笔记
在大多数情况下,您可以使用以下语法从事件中删除处理程序(委托):
backgroundworker.DoWork -= new DoWorkEventHandler(mehtod1);
或使用隐式或显式方法组转换:
backgroundworker.DoWork -= (DoWorkEventHandler)mehtod1; // explicit convertion
// - or -
backgroundworker.DoWork -= mehtod1; // implicit (more compact)
但根据具体情况,您可能需要维护对前一个委托的引用,以便以后能够将其删除。例如,这将适用于匿名方法或 lambda 表达式。
你可以用众所周知的“额外的间接级别”来解决这个问题。写一个这样的类:
public sealed class RedirectableDoWorkEventHandler
{
public RedirectableDoWorkEventHandler(DoWorkEventHandler handler)
{
Contract.Requires(handler != null);
_handler = handler;
}
public DoWorkEventHandler Handler
{
get
{
return _handler;
}
set
{
Contract.Requires(value != null);
_handler = value;
}
}
public void DoWork(object sender, DoWorkEventArgs e)
{
_handler(sender, e);
}
private DoWorkEventHandler _handler;
}
然后你可以像这样使用它:
public void Setup()
{
BackgroundWorker worker = new BackgroundWorker();
// ...
var handler = new RedirectableDoWorkEventHandler(handler1);
worker.DoWork += handler.DoWork;
// And then some time later...
handler.Handler = handler2; // Now DoWork will call handler2.
}
private void handler1(object sender, DoWorkEventArgs e)
{
// Whatever
}
private void handler2(object sender, DoWorkEventArgs e)
{
// Whatever
}
但实际上,有什么意义呢?您还不如只拥有一个简单的处理程序,可以if
在选项中进行选择。我想在某些情况下它可以帮助封装东西...... YMMV。