Подтвердить что ты не робот

Как повысить пользовательское событие из статического класса

У меня есть статический класс, который я хотел бы создать событие как часть блока catch try в статическом методе этого класса.

Например, в этом методе я хотел бы поднять пользовательское событие в catch.

public static void saveMyMessage(String message)
{
    try
    {
        //Do Database stuff
    }
    catch (Exception e)
        {
              //Raise custom event here
        }
}

Спасибо.

4b9b3361

Ответ 1

Важно: будьте очень осторожны с подпиской на статическое событие из экземпляров. Статический-статический - это хорошо, но подписка от статического события на обработчик экземпляра - отличный (читаемый: очень опасный) способ сохранить этот экземпляр живым навсегда. GC увидит ссылку и не будет собирать экземпляр, если вы не отмените подписку (или используйте что-то вроде WeakReference).

Шаблон для создания статических событий совпадает с событиями isntance, только с static:

public static event EventHandler SomeEvent;

Чтобы облегчить жизнь (повторная проверка), полезный трюк здесь заключается в добавлении тривиального обработчика:

public static event EventHandler SomeEvent = delegate {};

Затем вы можете просто вызвать его без нулевой проверки:

SomeEvent(null, EventArgs.Empty);

Обратите внимание, что поскольку экземпляры делегата являются неизменяемыми, а удаление ссылок является потокобезопасным, здесь никогда не существует условия гонки, и нет необходимости блокировать... кто когда-либо подписывается при вызове отмены ссылки.

(отрегулируйте свои собственные события-аргументы и т.д.). Этот трюк применим в равной степени к событиям экземпляра.

Ответ 2

Ваше событие также должно быть статическим:

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");

Ответ 3

Несколько человек предложили примеры кода, просто не запускайте событие с использованием кода, например:

if(null != ExampleEvent)
{
  ExampleEvent(/* put parameters here, for events: sender, eventArgs */);
}

поскольку это содержит условие гонки между тем, когда вы проверяете событие на null и когда вы действительно запускаете событие. Вместо этого используйте простую вариацию:

MyEvent exampleEventCopy = ExampleEvent;
if(null != exampleEventCopy)
{
  exampleEventCopy(/* put parameters here, for events: sender, eventArgs */);
}

Это скопирует всех подписчиков событий в exampleEventCopy, которые затем можно использовать как локальную версию публичного события, не беспокоясь о каких-либо условиях гонки (по сути, возможно, что другой поток может вас упредить сразу после того, как вы проверили публичное событие на null и приступите к удалению всех подписчиков из события, в результате чего последующее включение события вызовет исключение, используя копию локального кода, вы избегаете возможности использования других потоков, поскольку они не могут получить доступ к локальной переменной).

Ответ 4

Примечание: VS2008, С#

Просто объявите событие, как обычно, в статическом классе, но обязательно отметьте это событие как статическое:

public static event EventHandler Work;

Затем просто подпишитесь на него, как обычно.

Ответ 5

Просто добавьте "Делегаты неизменяемы" Итак, как показано в приведенном выше примере, следующая строка получает копию делегата.

EventHandler<ErrorEventArgs> errorEvent = OnError;