C中的事件驱动类#

问题描述:

我正在创建一个事件驱动类,以便当我将它传递给一系列数据时,它将处理并在准备就绪时返回值。C中的事件驱动类#

下面是我正在使用下面的代码,但它是相当讨厌的代码,我不知道是否可以比这更简单。

public delegate void MyEventHandler(double result); 

    public static MyEventHandler EventComplete; 

    public static void MakeSomethingHappen(double[] data) 
    { 
     ThreadPool.QueueUserWorkItem(DoSomething, data); 
    } 
    private static void DoSomething(object dblData) 
    { 
     InvokeEventComplete(AndSomethingElse((double[])dblData)); 
    } 

    private static void InvokeEventComplete(double result) 
    { 
     if (EventComplete != null) 
     { 
      EventComplete(result); 
     } 
    } 

    public static double AndSomethingElse(double[] data) 
    { 
     //do some code 
     return result; //double 
    } 

在我的主类我简单地挂上一个方法,像这样的情况下,

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete); 
+0

可能是更好的适合http://codereview.stackexchange.com – BoltClock 2011-05-14 17:51:51

+0

你真的需要一切是静态的吗?另外,请考虑遵循标准事件模式,其中代表是'EventHandler '。 – driis 2011-05-14 17:57:04

+0

@BoltClock我真的需要更多地关注SE通过Area51。好的发现:-) – 2011-05-14 18:22:17

给你:

  • 暴露事件作为一个真实的事件,而不是一个公开访问的成员代表。
  • 消除了额外的委托声明并使用了通用委托操作。
  • 消除了只是冗长的额外调用功能。
  • 使用lambda表达式进行事件注册。

编辑的代码是:

MyClass.EventComplete += (result) => Console.WriteLine("Result is: " + result); 

public class MyClass 
{ 
    public static event Action<double> EventComplete; 

    public static void MakeSomethingHappen(double[] data) 
    { 
     ThreadPool.QueueUserWorkItem(DoSomething, data); 
    } 

    private static void DoSomething(object dblData) 
    { 
     var result = AndSomethingElse((double[])dblData); 

     if (EventComplete != null) 
     { 
      EventComplete(result); 
     } 
    } 

    public static double AndSomethingElse(double[] data) 
    { 
     //do some code 
     return result; //double 
    } 
} 

有些事情要考虑...

有一个在.NET中EventHandler<T> where T : EventArgs,但权衡是你最终编写自定义EventArgs来传递你的双重数据,而不是一个自定义的委托。不过我认为这是一种更清晰的模式。

如果你要定义您的事件作为

public static MyEventHandler EventComplete = delegate {}; 
//using a no-op handler like this has implications on Garbage Collection 

Does using a no-op lambda expression for initializing an event prevent GC?

你能救自己的,如果(EventComplete!= NULL)每次检查,从而使调用......方法是多余的。

您还可以简化

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete); 
to 
MyClass.EventComplete += MyClass_EventComplete; 

除此之外,它看起来不错。我相信周围的所有代码static的是刚刚从一个ConsoleApplication工作:-)

尝试使用非标准的事件模式(千次内使用FCL)

// in [CompleteEventArgs.cs] file 
public class CompleteEventArgs : EventArgs { 
    private readonly double _result; 

    public CompleteEventArgs(double result) { 
     _result = result; 
    } 

    public double Result { 
     get { return _result; } 
    } 
} 

// inside your class 

// don't forget 'event' modifier(!) it prevents lots of illegal stuff 
// like 'Complete = null' on the listener side 
public static event EventHandler<CompleteEventArgs> Complete; 

public static void MakeSomethingHappen(double[] data) { 
    ThreadPool.QueueUserWorkItem(DoSomething, data); 
} 
private static void DoSomething(object dblData) { 
    OnComplete(new CompleteEventArgs(AndSomethingElse((double[])dblData))); 
} 

// if you're working with a 'normal' (non-static) class 
// here should be 'protected virtual' modifiers to allow inheritors 
// use polymorphism to change the business logic 
private static void OnComplete(CompleteEventArgs e) { 
    if (Complete != null) 
     Complete(null, e); // in 'normal' way here stands 'this' instead of 'null' 
          // this object (link to the sender) is pretty tricky 
          // and allows extra flexibility of the code on the listener side 
} 

public static double AndSomethingElse(double[] data) { 
    double result = 0; 
    //do some code 
    return result; //double 
} 
+0

@Kyle:请注意@ Teoman的答案中的类似错误(错误/错误)!事件必须(!)与“事件”修饰符一起使用。在他的代码中可以写MyClass.EventComplete = null;从代码的任何部分,它会导致可怕的事情发生;)甚至使用{get; private set;}是不好的。对不起,我没有足够的代表评论他的帖子 – Mikant 2011-05-14 18:16:16