繁体   English   中英

如何从静态类引发自定义事件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM