Как вызвать обработчик события внутри асинхронного обратного вызова, который выполняется в вызывающем потоке
Я работаю над проектом / решением VS, который используется различными приложениями. Моя работа состоит в том, чтобы реорганизовать проект и изменить его с помощью метода xxxAsync на использование BeginInvoke.
Я пришел к чему-то похожему на следующий код:
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;
}
}
}
Я протестировал это на новом проекте пользовательского интерфейса, который я создал. Проект пользовательского интерфейса содержит кнопку и метку управления. Пользовательский интерфейс имеет следующий код:
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;
}
После выполнения этого я столкнулся с межпотоковым исключением, в котором говорится, что к элементу управления «label1» обращаются из другого потока, кроме созданного им потока.
Есть ли способ для меня, чтобы вызвать обработчик события OnTaskCompleted в том же потоке, который вызывает метод BeginInvoke? Я знаю, что мог бы просто использовать InvokeRequired формы и вызвать BeginInvoke формы следующим образом:
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;
}
Но приведенное выше решение потребует, чтобы я попросил и применил это решение к другой группе разработчиков, которая обрабатывает приложения, использующие мой проект / решение. Этим другим разработчикам не нужно знать, что методы, подключенные к обработчику событий, выполняются из другого потока.
Заранее спасибо.