Aufrufen der Ereignisbehandlungsroutine in einem asynchronen Rückruf, der im aufrufenden Thread ausgeführt wird

Ich arbeite an einem VS-Projekt / einer VS-Lösung, die von verschiedenen Anwendungen verwendet wird. Meine Aufgabe ist es, das Projekt umzugestalten und von der xxxAsync-Methode zur BeginInvoke-Methode zu wechseln.

Ich bin auf etwas gekommen, das dem folgenden Code ähnelt:

public class AsyncTestModel {
    private delegate string DoTaskDelegate();

    public static EventHandler<TaskCompletedEventArgs> OnTaskCompleted;

    public static void InvokeTask() {
        DoTaskDelegate taskDelegate = Task;
        taskDelegate.BeginInvoke(new AsyncCallback(TaskCallback), null);
    }

    private static string Task() {
        Thread.Sleep(5000);
        return "Thread Task successfully completed.";
    }

    private static void TaskCallback(IAsyncResult ar) {
        string result = ((DoTaskDelegate)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
        if (OnTaskCompleted != null) {
            OnTaskCompleted(null, new TaskCompletedEventArgs(result));
        }
    }
}

public class TaskCompletedEventArgs : EventArgs {
    private string _message;

    public TaskCompletedEventArgs(string message) : base() {
        _message = message;
    }

    public string Message {
        get {
            return _message;
        }
    }
}

Ich habe dies in einem neuen UI-Projekt getestet, das ich erstellt habe. Das UI-Projekt enthält eine Schaltfläche und ein Label-Control. Die Benutzeroberfläche hat den folgenden Code:

    private void button1_Click(object sender, EventArgs e) {
        AsyncTestModel.OnTaskCompleted += OnTaskCompleted;
        AsyncTestModel.InvokeTask();
    }

    private void OnTaskCompleted(object sender, TaskCompletedEventArgs e) {
        UpdateLabel(e.Message);
    }

    private void UpdateLabel(string message) {
        this.label1.Text = message;
    }

Nachdem ich dies ausgeführt habe, bin ich auf die Cross-Thread-Ausnahme gestoßen, die besagt, dass auf das Steuerelement 'label1' von einem anderen Thread zugegriffen wird, abgesehen von dem Thread, den es erstellt hat.

Gibt es eine Möglichkeit für mich, den OnTaskCompleted-Ereignishandler in demselben Thread aufzurufen, der die BeginInvoke-Methode aufruft? Ich weiß, ich könnte einfach InvokeRequired des Formulars verwenden und BeginInvoke des Formulars wie folgt aufrufen:

    private delegate void DoUpdateLabelDelegate(string message);

    private void UpdateLabel(string message) {
        if (this.InvokeRequired) {
            IAsyncResult ar = this.BeginInvoke(new DoUpdateLabelDelegate(UpdateLabel), message);
            this.EndInvoke(ar);
            return;
        }
        this.label1.Text = message;
    }

Die obige Lösung erfordert jedoch, dass ich nach dieser Lösung frage und sie auf die anderen Anwendungen des Entwicklungsteams anwende, die mein Projekt / meine Lösung verwenden. Diese anderen Entwickler sollten nicht wissen müssen, dass die an den Ereignishandler gebundenen Methoden von einem anderen Thread ausgeführt werden.

Danke im Voraus.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage