假设我有一个名为 Tasking 的组件(我无法修改),它公开了一个方法“DoTask”,该方法执行一些可能冗长的计算并通过事件 TaskCompleted 返回结果。通常这是在用户获得结果后关闭的窗口形式中调用的。
在我的特定场景中,我需要将一些数据(数据库记录)与 TaskCompleted 返回的数据相关联,并使用它来更新数据库记录。
我调查了使用 AutoResetEvent 来通知事件何时被处理。问题是 AutoResetEvent.WaitOne() 将阻塞并且永远不会调用事件处理程序。通常 AutoResetEvents 被称为是一个单独的线程,所以我猜这意味着事件处理程序与调用的方法位于同一线程上。
本质上,我想通过阻塞将异步调用(结果通过事件返回)转换为同步调用(即从另一个类调用 DoSyncTask),直到事件被处理并且结果放置在事件处理程序都可以访问的位置以及调用启动异步调用的方法的方法。
public class SyncTask
{
TaskCompletedEventArgs data;
AutoResetEvent taskDone;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
taskDone.WaitOne(); // but something more like Application.DoEvents(); in WinForms.
taskDone.Reset();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
taskDone.Set(); //or some other mechanism to signal to DoSyncTask that the work is complete.
}
}
In a Windows App the following works correctly.
public class SyncTask
{
TaskCompletedEventArgs data;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
while (data == null) Application.DoEvents();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
}
}
我只需要在不调用 Application.Run 且 ApplicationContext 对象不可用的窗口服务中复制该行为。