tags:

views:

1970

answers:

6

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.

For example in this method I would like to raise a custom event in the catch. An advice, code samples would be helpful.

public static void saveMyMessage(String message) {

try
{
    //Do Database stuff
}
catch (Exception e)
    {
          //Raise custom event here
    }

}

Thank you.

A: 

Note: 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.

Re "as you normally would" - you need to be more cautious with static events, especially re unsubscribing. That will work in any version of C# btw.
Marc Gravell
A: 

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");
Todd
A: 

Todd - you said

Your event handler would also need to be static

But it doesn't have to be, as your code example shows. What would have to be static?

Mike, this is not an answer to the question. Use the "add comment" for commenting on answers.
mr_georg
Adding comments requires 50 reputation points, which Mike does not have.
Brian B.
Sorry the event must be static. EventHandler<T> in the example.
Todd
+2  A: 

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).

Brian B.
An easier fix is: public static event EventHandler Work = delegate { }; Now it is never null and you can just invoke it. Slightly lazy, but not enough to hurt.
Marc Gravell
+11  A: 

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 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).

The pattern for creating static events is the same as isntance events, just with 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.

Marc Gravell
A: 

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;
Nelson P. Varghese