C# 如何从静态类引发自定义事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/289002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to raise custom event from a Static Class
提问by Avitus
I have a static class that I would like to raise an event as part of a try catch block within a static method of that class.
我有一个静态类,我想在该类的静态方法中引发一个事件作为 try catch 块的一部分。
For example in this method I would like to raise a custom event in the catch.
例如,在这个方法中,我想在 catch 中引发一个自定义事件。
public static void saveMyMessage(String message)
{
try
{
//Do Database stuff
}
catch (Exception e)
{
//Raise custom event here
}
}
Thank you.
谢谢你。
采纳答案by Marc Gravell
Important: be very careful about subscribing to a static event from instances. Static-to-static is fine, but a subscription from a static event to an instance handler is a great (read: very dangerous) way to keep that instance alive forever. GC will see the link, and will not collect the instance unless you unsubscribe (or use something like a WeakReference).
重要提示:从实例订阅静态事件时要非常小心。静态到静态很好,但是从静态事件到实例处理程序的订阅是一种很好(阅读:非常危险)的方式,可以使该实例永远保持活动状态。GC 将看到链接,并且不会收集实例,除非您取消订阅(或使用类似 WeakReference 的东西)。
The pattern for creating static events is the same as instance events, just with static
:
创建静态事件的模式与实例事件相同,只是static
:
public static event EventHandler SomeEvent;
To make life easier (re null checking), a useful trick here is to add a trivial handler:
为了让生活更轻松(重新检查空值),这里一个有用的技巧是添加一个简单的处理程序:
public static event EventHandler SomeEvent = delegate {};
Then you can simply invoke it without the null-check:
然后你可以简单地调用它而无需空检查:
SomeEvent(null, EventArgs.Empty);
Note that because delegate instances are immutable, and de-referencing is thread-safe, there is never a race condition here, and no need to lock... who-ever is subscribed when we de-reference gets invoked.
请注意,因为委托实例是不可变的,并且取消引用是线程安全的,所以这里永远不会出现竞争条件,也不需要锁定......当我们取消引用被调用时,订阅了谁。
(adjust for your own event-args etc). This trick applies equally to instance events.
(根据您自己的事件参数等进行调整)。这个技巧同样适用于实例事件。
回答by Avitus
Note: VS2008, C#
注意:VS2008,C#
Just declare an event as you normally would within the static class, but be sure to mark the event as static:
只需像往常一样在静态类中声明一个事件,但一定要将该事件标记为静态:
public static event EventHandler Work;
Then just subscribe to it as you normally would.
然后像往常一样订阅它。
回答by Todd
Your event would also need to be static:
您的活动还需要是静态的:
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));
}
}
}
And Usage:
和用法:
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");
回答by Brian B.
Several folks have offered up code examples, just don't fire an event using code such as:
有几个人提供了代码示例,只是不要使用以下代码触发事件:
if(null != ExampleEvent)
{
ExampleEvent(/* put parameters here, for events: sender, eventArgs */);
}
as this contains a race condition between when you check the event for null and when you actually fire the event. Instead use a simple variation:
因为这包含您检查事件是否为空和实际触发事件之间的竞争条件。而是使用一个简单的变体:
MyEvent exampleEventCopy = ExampleEvent;
if(null != exampleEventCopy)
{
exampleEventCopy(/* put parameters here, for events: sender, eventArgs */);
}
This will copy any event subscribers into the exampleEventCopy, which you can then use as a local-only version of the public event without having to worry about any race conditions (Essentially, it is possible that another thread could pre-empt you right after you have checked the public event for null and proceed to remove all subscribers from the event, causing the subsequent firing of the event to throw an exception, by using a local-only copy, you avoid the possibility of another thread removing subscribers, since there is no way they could access the local variable).
这会将任何事件订阅者复制到 exampleEventCopy 中,然后您可以将其用作公共事件的仅限本地版本而不必担心任何竞争条件(本质上,另一个线程可能会在您之后抢占您已检查公共事件是否为 null 并继续从事件中删除所有订阅者,导致事件的后续触发引发异常,通过使用仅本地副本,您可以避免另一个线程删除订阅者的可能性,因为有他们无法访问局部变量)。
回答by Nelson P. Varghese
Just to add "Delegates are immutable" So, as shown in the example above the following line obtains a copy of the delegate.
只是为了添加“委托是不可变的”所以,如上面的示例所示,以下行获取委托的副本。
EventHandler<ErrorEventArgs> errorEvent = OnError;