Работают ли события, если возникают асинхронно? - PullRequest
2 голосов
/ 21 ноября 2010

У меня есть следующий скелет класса. Как вы можете видеть в комментарии TODO: здесь я буду реализовывать конструкцию AsyncEnumerator. Этот метод захватит запрос и передаст данные другому методу для обработки. Основываясь на процессе, я хотел бы вызывать события либо SendMilestoneReached, либо SendFailed. Я беспокоюсь, что это может произойти в другом потоке из-за AsyncEnumerator.

Это повлияет на поток пользовательского интерфейса, где будет вызываться класс Webtext?

/// <summary>
/// Sends Webtexts.
/// </summary>
public class Webtext
{
    #region Event Definitions

    // Events.
    public event EventHandler<SendingEventArgs> SendStarted = delegate { };
    public event EventHandler<SendingEventArgs> SendFailed = delegate { };
    public event EventHandler<SendingEventArgs> SendSuccessful = delegate { };
    public event EventHandler<SendingEventArgs> SendMilestoneReached = delegate { };

    // Shared EventArgs Object, Consumed by the Events.
    SendingEventArgs EventArgs = new SendingEventArgs();

    #endregion

    /// <summary>
    /// Executes the send request.
    /// </summary>
    /// <param name="Operator">The operator whos service to use.</param>
    /// <param name="Username">The username of the requested operator.</param>
    /// <param name="Password">The password of the requested operator.</param>
    /// <param name="Content">The content to send.</param>
    /// <param name="Recipient">The recipient to recieve the content.</param>
    public void ExecuteSendRequest(string Operator, 
                                   string Username, 
                                   string Password, 
                                   string Content, 
                                   string Recipient)
    {
        //TODO: Implement Async requests here.
    }

    #region Event Handlers

    /// <summary>
    /// Called when [sending started].
    /// </summary>
    protected void OnSendingStarted()
    {
        SendStarted(this, EventArgs);
    }

    /// <summary>
    /// Called when [send fail].
    /// </summary>
    protected void OnSendFail()
    {
        SendFailed(this, EventArgs);
    }

    /// <summary>
    /// Called when [send successful].
    /// </summary>
    protected void OnSendSuccessful()
    {

        SendSuccessful(this, EventArgs);
    }

    /// <summary>
    /// Called when [send milestone reached].
    /// </summary>
    protected void OnSendMilestoneReached()
    {
        SendMilestoneReached(this, EventArgs);
    }

    #endregion


}

Ответы [ 2 ]

3 голосов
/ 21 ноября 2010

Обратите внимание, что если вы вызываете события асинхронно и обработчики должны обновить пользовательский интерфейс, им нужно будет синхронизироваться с потоком пользовательского интерфейса для обновления любых пользовательских элементов управления.Если вы генерируете события асинхронно, вы возлагаете большую нагрузку на классы, которые подписываются на ваши события: они должны знать, как выполнять синхронизацию потоков пользовательского интерфейса.

Для меня в целом Я обнаружил, что асинхронные события не стоят проблем, потому что почти всегда мне приходится обрабатывать эти события в программах пользовательского интерфейса.Я пришел к выводу, что если я хочу, чтобы события обрабатывались асинхронно, обработчик должен об этом позаботиться.

Это не сложное и быстрое правило.Ни в коем случае.Например, System.Timers.Timer по умолчанию вызывает событие в потоке ThreadPool, но вы можете указать SynchronizingObject, чтобы он мог синхронизироваться с потоком пользовательского интерфейса.

Если вы решили использовать асинхронные события, тогдаЯ предлагаю вам включить такое средство, как SynchronizingObject Timer, чтобы клиенты UI могли использовать ваш класс, не разбираясь со сложностями синхронизации потоков UI.

3 голосов
/ 21 ноября 2010

Событие создается тем же Thread, который его вызвал.Этот принцип звучит просто, но важно знать.

Итак:

Сценарий 1 Приложение открыто.Webtext инициализируется формой в потоке пользовательского интерфейса и вызывается его отправка.Webtext отправляет запрос синхронно и запускает событие.В течение всего времени все операции выполняются в потоке пользовательского интерфейса.

Сценарий 2 Приложение открыто.Webtext инициализируется формой в потоке пользовательского интерфейса и вызывается его отправка.Webtext отправляет запрос Асинхронно с использованием рабочего потока.Второй поток запускает событие, когда оно закончено.Это будет рабочий поток (фон или передний план в зависимости от того, как вы создаете поток).Любой вызов через этот поток к элементам пользовательского интерфейса должен быть выполнен с использованием Invoke.

. Как вы можете видеть, очень сильно зависит от того, как вы реализуете метод send. Я не вижу ни одногореализация самой отправки, поэтому все, что я могу сказать - если вы создаете поток или используете пул потоков, он будет в рабочем потоке, в противном случае синхронная отправка будет выполняться в потоке пользовательского интерфейса.

...