3

I am creating an event driven class so that when I pass it a series of data, it will process and then return the value when ready.

Below is the code that I am currently using the below code however it is quite nasty and I'm not sure if can be simpler than this.

   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
    }

In my main class I simply hook up a method to the event like so,

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);
3
  • Might be a better fit for codereview.stackexchange.com Commented May 14, 2011 at 17:51
  • Do you really need everything to be static ? Also, consider following the standard event pattern where the delegate is EventHandler<T>. Commented May 14, 2011 at 17:57
  • @BoltClock I really need to pay more attention to the SE's coming through Area51. good find :-) Commented May 14, 2011 at 18:22

3 Answers 3

3

Here you are:

  • Exposed event as an actual event rather than a publicly accessible member delegate.
  • Eliminated extra delegate declaration and used generic delegate Action.
  • Eliminated extra invocation function which was simply verbose.
  • Used lambda expression for event registration.

Edited code is:

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
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Some things to consider...

There's an EventHandler<T> where T : EventArgs in .NET, but the trade off is you end up writing a custom EventArgs to pass your double data instead of a custom delegate. Still I think that's a cleaner pattern to follow.

If you were to define your event as

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?

you could save yourself the if(EventComplete != null) check everytime and hence make the Invoke... method redundant.

you can also simplify

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

Aside from that it looks fine. I presume all the static's around the code are just from working in a ConsoleApplication :-)

Comments

0

try using standart event pattern (thousands times used inside 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
}

1 Comment

@Kyle: please note the similar error (bug/mistake) in @Teoman's answer! event must(!) be field with 'event' modifier. in his code it is possible to write MyClass.EventComplete = null; from any part of the code and it will cause terrible things happen;) even using {get;private set;} is bad. sorry, I don't have enough rep to comment his post

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.