[英]How to raise custom event from a Static Class
我有一个静态类,我想在该类的静态方法中引发一个事件作为 try catch 块的一部分。
例如,在这个方法中,我想在 catch 中引发一个自定义事件。
public static void saveMyMessage(String message)
{
try
{
//Do Database stuff
}
catch (Exception e)
{
//Raise custom event here
}
}
谢谢你。
重要提示:从实例订阅静态事件时要非常小心。 静态到静态很好,但是从静态事件到实例处理程序的订阅是一种很好(阅读:非常危险)的方式,可以使该实例永远保持活动状态。 GC 将看到链接,并且不会收集实例,除非您取消订阅(或使用类似 WeakReference 的东西)。
创建静态事件的模式与实例事件相同,只是使用static
:
public static event EventHandler SomeEvent;
为了让生活更轻松(重新检查空值),这里一个有用的技巧是添加一个简单的处理程序:
public static event EventHandler SomeEvent = delegate {};
然后你可以简单地调用它而无需空检查:
SomeEvent(null, EventArgs.Empty);
请注意,因为委托实例是不可变的,并且取消引用是线程安全的,所以这里永远不会出现竞争条件,也不需要锁定......当我们取消引用被调用时,订阅了谁。
(根据您自己的事件参数等进行调整)。 这个技巧同样适用于实例事件。
您的活动还需要是静态的:
public class ErrorEventArgs : EventArgs
{
private Exception error;
private string message;
public ErrorEventArgs(Exception ex, string msg)
{
error = ex;
message = msg;
}
public Exception Error
{
get { return error; }
}
public string Message
{
get { return message; }
}
}
public static class Service
{
public static EventHandler<ErrorEventArgs> OnError;
public static void SaveMyMessage(String message)
{
EventHandler<ErrorEventArgs> errorEvent = OnError;
if (errorEvent != null)
{
errorEvent(null, new ErrorEventArgs(null, message));
}
}
}
和用法:
public class Test
{
public void OnError(object sender, ErrorEventArgs args)
{
Console.WriteLine(args.Message);
}
}
Test t = new Test();
Service.OnError += t.OnError;
Service.SaveMyMessage("Test message");
有几个人提供了代码示例,只是不要使用以下代码触发事件:
if(null != ExampleEvent)
{
ExampleEvent(/* put parameters here, for events: sender, eventArgs */);
}
因为这包含您检查事件是否为空和实际触发事件之间的竞争条件。 而是使用一个简单的变体:
MyEvent exampleEventCopy = ExampleEvent;
if(null != exampleEventCopy)
{
exampleEventCopy(/* put parameters here, for events: sender, eventArgs */);
}
这会将任何事件订阅者复制到 exampleEventCopy 中,然后您可以将其用作公共事件的仅限本地版本,而不必担心任何竞争条件(本质上,另一个线程可能会在您之后抢占您已检查公共事件是否为 null 并继续从事件中删除所有订阅者,导致事件的后续触发引发异常,通过使用仅本地副本,您可以避免另一个线程删除订阅者的可能性,因为有他们无法访问局部变量)。
只是为了添加“委托是不可变的”所以,如上面的示例所示,以下行获取委托的副本。
EventHandler<ErrorEventArgs> errorEvent = OnError;
注意:VS2008,C#
只需像往常一样在静态类中声明一个事件,但一定要将该事件标记为静态:
public static event EventHandler Work;
然后像往常一样订阅它。
我这样做的方式如下:
1- 定义一个委托(这将使您能够拥有自定义参数):
public delegate void CustomeEventHandler(string str);
2- 根据之前定义的委托定义一个事件:
public static event CustomeEventHandler ReadLine;
3- 创建一个事件处理程序:
static void OnLineRead(string currentLine)
{
if (ReadLine != null)
ReadLine(currentLine);
}
4- 使用事件处理程序引发您的事件(只需在您想要引发事件的任何地方调用它)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.