【发布时间】:2009-01-28 03:32:04
【问题描述】:
假设我有一个名为 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 对象不可用。
【问题讨论】:
-
这里有一个很好的视频了解
AutoResetEventyoutube.com/watch?v=xaaRBh07N34
标签: c# multithreading events delegates