在我的代码中,我需要取消注册并注册一个事件处理程序,这非常有效:
_favoritsImageView.Click -= _favoritsImageView_Click(this, new CustomeClickEventArgs(item));
_favoritsImageView.Click += _favoritsImageView_Click(this, new CustomeClickEventArgs(item));
void _favoritsImageView_Click(object sender, CustomeClickEventArgs e)
{
// handles the event
}
Run Code Online (Sandbox Code Playgroud)
但对于一个等待的事件处理程序,我必须使用以下语法:
_favoritsImageView.Click -= async (s, e) =>
{ await _favoritsImageView_ClickAsync(s, new CustomeClickEventArgs(item)); };
_favoritsImageView.Click += async (s, e) =>
{ await _favoritsImageView_ClickAsync(s, new CustomeClickEventArgs(item)); };
async Task _favoritsImageView_ClickAsync(object sender, CustomeClickEventArgs e)
{
// does async task
}
Run Code Online (Sandbox Code Playgroud)
这不起作用.因为匿名方法没有相同的引用.因此第一行不会取消注册已注册的处理程序.最后,第二行为点击添加了额外的事件处理程序.
我需要使用哪种语法来添加和删除异步事件处理程序?
谢谢你的任何建议.
我经常遇到想要订阅事件的情况,但我想使用lambda来执行此操作:
public class Observable
{
public event EventHandler SomethingHappened;
public void DoSomething()
{
// Do Something...
OnSomethingHappened();
}
}
// Somewhere else, I hook the event
observable.SomethingHappened += (sender, args) => Console.WriteLine("Something Happened");
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是我不知道如何取消事件.由于lambda在引擎盖下创建了一个匿名委托,所以我没有什么可以调用-=的.
现在,我可以创建一个方法:
private void SomethingHappened(object sender, EventArgs args)
{
Console.WriteLine("Something Happened");
}
Run Code Online (Sandbox Code Playgroud)
然后我可以挂钩/取消所有我想要的东西:
observable.SomethingHappened += SomethingHappened;
observable.SomethingHappened -= SomethingHappened;
Run Code Online (Sandbox Code Playgroud)
但我真的非常非常喜欢使用我的lambda.在一个更复杂的例子中,lambdas在这里非常方便.
我很确定我运气不好......但我想知道是否有人想出办法做到这一点?
如果我创建一个lambda回调,如下所示:
var someInstance = new SomeObject();
someInstance.Finished += (obj, args) =>
{
// Do something
// Deregister here
};
someInstance.DoAction();
Run Code Online (Sandbox Code Playgroud)
我如何取消注册回调作为实际处理程序代码的一部分?这种模式是理想的,因为我可以确保它尽快释放.
我见过类似的问题但不是直接解决这类例子的问题.
C#2.0有一个称为匿名函数的简洁功能.这主要用于事件:
Button.Click += delegate(System.Object o, System.EventArgs e)
{ System.Windows.Forms.MessageBox.Show("Click!"); };
Run Code Online (Sandbox Code Playgroud)
现在,假设Button是一个静态成员,那么向其添加委托将被视为非托管资源.通常,我必须在再次对其进行regestring之前取消注册该处理程序.这是GUI编程的一个非常常见的用例.
匿名函数有哪些指导原则?框架是否自动取消注册?如果是的话,何时?
可能重复:
在C#中取消订阅匿名方法
我有一些Panels,在创建时,他们被委派为可点击:
int z2 = z;
PicBx[z].Click += delegate { clicked(z2, null); };
Run Code Online (Sandbox Code Playgroud)
如果程序要求它,我希望能够删除它.我试过用:
int z2 = z;
PicBx[z].Click -= delegate { clicked(z2, null); };
Run Code Online (Sandbox Code Playgroud)
但它没有用.有没有办法从中删除可点击的委托?
我被添加到Application的处理程序:
Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, null);
Run Code Online (Sandbox Code Playgroud)
在此之后我想添加另一个处理程序
Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, param);
Run Code Online (Sandbox Code Playgroud)
我如何删除以前的处理程序?
当我从Control中删除处理程序时,我只需使用:
public void RemoveOnThreadException(SimpleButton b)
{
FieldInfo f1 = typeof(Control).GetField("EventClick",
BindingFlags.Static | BindingFlags.NonPublic);
object obj = f1.GetValue(b);
PropertyInfo pi = b.GetType().GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
list.RemoveHandler(obj, list[obj]);
}
Run Code Online (Sandbox Code Playgroud)
我如何使用Application和AppDomain做同样的事情?
@Andrey有我用Button.Click的尝试:
public TestForm()
{
InitializeComponent();
simpleButton1.Click += (sender, a) => simpleButton1_Click(sender,a);
simpleButton1.Click -= simpleButton1_Click;
simpleButton1.Click += (sender, a) => simpleButton1_Click(sender, a);
}
private void simpleButton1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hi"); …Run Code Online (Sandbox Code Playgroud) 我以这种方式订阅活动:
s1.MouseUp += (s, e) =>
{
indexOfPointToMove = -1;
s1.LineStyle = LineStyle.Solid;
MyModel.RefreshPlot(false);
e.Handled = true;
};
Run Code Online (Sandbox Code Playgroud)
我怎么能在不同的范围内取消订阅?(但在范围内s1)
我尝试过以下方法:
s1.MouseUp = null;
s1.MouseUp -=(s,e) =>
{
indexOfPointToMove = -1;
s1.LineStyle = LineStyle.Solid;
MyModel.RefreshPlot(false);
e.Handled = true;
};
s1.MouseUp += (s,e) =>
{
//nothing
};
Run Code Online (Sandbox Code Playgroud)
但事件还在解决,怎么办呢?