Can I have exceptional security and events?

Suppose I have a method that changes the state of an object and fires an event to notify listeners of this state change:

public class Example
{
   public int Counter { get; private set; }

   public void IncreaseCounter()
   {
      this.Counter = this.Counter + 1;
      OnCounterChanged(EventArgs.Empty);
   }

   protected virtual void OnCounterChanged(EventArgs args)
   {
      if (CounterChanged != null)
         CounterChanged(this,args);
   }

   public event EventHandler CounterChanged;
}

Event handlers may throw an exception even if they IncreaseCountersuccessfully complete the state change. Thus, we do not have strong exception safety here:

Strong guarantee: that the operation completed successfully or throws an exception, leaving the program state exactly as it was before the operation began.

Is it possible to have strong exception protection if you need to raise events?

+5
source share
5 answers

, , MultiCast (.. ) try-catch

, .

public EventHandler<EventArgs> SomeEvent;

protected void OnSomeEvent(EventArgs args)
{
    var handler = SomeEvent;
    if (handler != null)
    {
        foreach (EventHandler<EventArgs> item in handler.GetInvocationList())
        {
            try
            {
                item(this, args);
            }
            catch (Exception e)
            {
                // handle / report / ignore exception
            }
        }                
    }
}

, , , - . () , , , .

, . , . , , , - .

+3

, :

public class Example
{
   public int Counter { get; private set; }

   public void IncreaseCounter()
   {
      OnCounterChanging(EventArgs.Empty);
      this.Counter = this.Counter + 1;
      OnCounterChanged(EventArgs.Empty);
   }

   protected virtual void OnCounterChanged(EventArgs args)
   {
      if (CounterChanged != null)
         CounterChanged(this, args);
   }

   protected virtual void OnCounterChanging(EventArgs args)
   {
      if (CounterChanging != null)
         CounterChanging(this, args);
   }

   public event EventHandler<EventArgs> CounterChanging;
   public event EventHandler<EventArgs> CounterChanged;
}

, , OnCounterChanging() OnCounterChanged(). ( , -ed), , .

Edit:

, , , try..catch/finally ( try..finally), . .. win32 , , , , ( , ). , .

+2

, , :

public void IncreaseCounter()
{
  int oldCounter = this.Counter;
  try {
      this.Counter = this.Counter + 1;
      OnCounterChanged(EventArgs.Empty);
  } catch {
      this.Counter = oldCounter;
      throw;
  }
}

, , ( ). bolierplate:

void SetField<T>(ref T field, T value, EventHandler handler) {
    T oldValue = field;
    try {
         field = value;
         if(handler != null) handler(this, EventArgs.Empty);
    } catch {
         field = oldField;
         throw;
    }
}

:

SetField(ref counter, counter + 1, CounterChanged);

- ...

+1

IncreaseCounter securecestrong ?

, Counter , :

public void IncreaseCounter()
{
    this.Counter += 1;

    try
    {
        OnCounterChanged(EventArgs.Empty);
    }
    catch
    {
        this.Counter -= 1;

        throw;
    }
}

, ( ), (, ), .

0

, , Workflow Foundation. OnCounterChanged try-catch. , - .

0

All Articles