Jak wywołać procedurę obsługi zdarzeń w asynchronicznym wywołaniu zwrotnym, które jest uruchamiane w wątku wywołującym

Pracuję nad projektem / rozwiązaniem VS, które jest używane przez różne aplikacje. Moim zadaniem jest refaktoryzacja projektu i zmiana go z używania metody xxxAsync na używanie BeginInvoke.

Doszedłem do czegoś podobnego do następującego kodu:

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;
        }
    }
}

Przetestowałem to na nowym projekcie interfejsu użytkownika, który stworzyłem. Projekt interfejsu użytkownika zawiera przycisk i elementy sterujące etykietą. Interfejs użytkownika ma następujący kod:

    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;
    }

Po uruchomieniu tego problemu natknąłem się na wyjątek między wątkami, mówiąc, że kontrolka „label1” jest dostępna z innego wątku poza wątkiem, który został utworzony.

Czy istnieje sposób, aby wywołać moduł obsługi zdarzenia OnTaskCompleted w tym samym wątku, który wywołuje metodę BeginInvoke? Wiem, że mogę po prostu użyć InvokeRequired formularza i wywołać BeginInvoke formularza w następujący sposób:

    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;
    }

Ale powyższe rozwiązanie będzie wymagało ode mnie pytania i zastosowania tego rozwiązania do innych zespołów programistycznych obsługujących aplikacje korzystające z mojego projektu / rozwiązania. Nie powinno się wymagać, aby ci inni programiści wiedzieli, że metody podłączone do obsługi zdarzeń działają z innego wątku.

Z góry dziękuję.

questionAnswers(2)

yourAnswerToTheQuestion