2 Stimmen

Funktionieren Ereignisse, wenn sie asynchron ausgelöst werden?

Ich habe das folgende Skelett einer Klasse. Wie Sie im TODO: Kommentar sehen können, werde ich hier ein AsyncEnumerator-Konstrukt implementieren. Diese Methode wird eine Anfrage aufnehmen und die Daten an eine andere Methode zur Verarbeitung weitergeben. Basierend auf dem Prozess möchte ich die Ereignisse, entweder SendMilestoneReached oder SendFailed, aufrufen. Ich bin besorgt, dass diese aufgrund des AsyncEnumerators auf einem anderen Thread stattfinden könnten.

Wird dies eine Auswirkung auf den UI-Thread haben, wo die Webtext-Klasse aufgerufen wird?

/// <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

}

3voto

Aliostad Punkte 78595

Ereignis wird von der gleichen Thread die sie aufgeworfen hat. Dieser Grundsatz klingt einfach, ist aber wichtig zu wissen.

Also:

Szenario 1 App wird geöffnet. Webtext wird durch das Formular im UI-Thread initialisiert und sein Senden aufgerufen. Webtext sendet die Anfrage synchron und löst das Ereignis aus. Während der gesamten Zeit werden alle Vorgänge auf dem UI-Thread ausgeführt.

Szenario 2 App wird geöffnet. Webtext wird durch das Formular im UI-Thread initialisiert und sein Senden aufgerufen. Webtext sendet die Anfrage Asynchron unter Verwendung eines Worker-Threads. Der zweite Thread feuert das Ereignis ab, wenn er fertig ist. Dies wird der Worker-Thread sein (Hintergrund oder Vordergrund, je nachdem, wie Sie den Thread erstellen). Jeder Aufruf von UI-Elementen durch diesen Thread muss mit Invoke .

Wie Sie sehen können, Es hängt sehr stark davon ab, wie Sie die Sendemethode implementieren. Ich kann keine Implementierung des Sendens selbst sehen, so dass alles, was ich sagen kann, ist, wenn Sie einen Thread erstellen oder Threadpool verwenden es auf dem Worker-Thread sonst einfach synchron senden auf UI-Thread sein wird.

3voto

Jim Mischel Punkte 125706

Beachten Sie, dass, wenn Sie Ereignisse asynchron auslösen und die Handler die Benutzeroberfläche aktualisieren müssen, sie sich mit dem UI-Thread synchronisieren müssen, um alle Benutzersteuerelemente zu aktualisieren. Wenn Sie Ereignisse asynchron auslösen, erlegen Sie den Klassen, die Ihre Ereignisse abonnieren, eine größere Last auf: Sie müssen wissen, wie sie die UI-Thread-Synchronisierung durchführen können.

Für mich, im Allgemeinen Ich habe festgestellt, dass asynchrone Ereignisse die Mühe nicht wert sind, weil ich am Ende fast immer diese Ereignisse in UI-Programmen behandeln muss. Ich kam zu dem Schluss, dass, wenn ich will, dass Ereignisse asynchron behandelt werden, dann sollte der Handler kümmern sich um das.

Dies ist keine feste Regel. Ganz und gar nicht. Zum Beispiel, System.Timers.Timer löst das Ereignis standardmäßig auf einem ThreadPool-Thread aus, aber Sie können einen SynchronizingObject damit er sich mit dem UI-Thread synchronisieren kann.

Wenn Sie sich für asynchrone Ereignisse entscheiden, dann schlage ich vor, dass Sie eine Funktion wie die des Timers SynchronizingObject so dass UI-Clients Ihre Klasse verwenden können, ohne sich mit der komplexen Synchronisierung von UI-Threads herumschlagen zu müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X