假设我有一个名为Tasking的组件(无法修改),它公开了一个方法“DoTask”,该方法执行一些可能很长的计算,并通过事件TaskCompleted返回结果。通常,这在用户关闭获取结果后的窗体中调用。
在我的特定情况下,我需要将一些数据(数据库记录)与通过TaskCompleted返回的数据关联起来,并使用它来更新数据库记录。
我已经研究了使用AutoResetEvent来通知事件何时被处理。问题在于AutoResetEvent.WaitOne()会阻塞,并且事件处理程序永远不会被调用。通常,AutoResetEvents由单独的线程调用,因此我想这意味着事件处理程序位于调用方法的线程上。
本质上,我想将异步调用(其中通过事件返回结果)转换为同步调用(即从另一个类调用DoSyncTask),通过阻塞直到事件被处理并将结果放置在对事件处理程序和调用启动异步调用的方法都可访问的位置。
在我的特定情况下,我需要将一些数据(数据库记录)与通过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对象不可用。
AutoResetEvent
。http://www.youtube.com/watch?v=xaaRBh07N34 - Jaider