我们有这种常见的场景,我们有一个方法可以异步执行某些操作,并在完成时引发一个事件.
有时我们希望它同步完成,所以我们有类似于这样的代码:
ManualResetEvent reset = new ManualResetEvent(false);
someobject.AsyncActionDone += (sender, args) => reset.Set();
someobject.PerformAsyncAction();
reset.WaitOne();
Run Code Online (Sandbox Code Playgroud)
有没有办法编写辅助方法来做到这一点?我可以传递Action来执行,但是我不确定如何传递让helper方法知道要侦听哪个事件的东西,因为它看起来不像你可以将EventHandler作为参数传递.
优选地,不需要反射的解决方案
似乎有一些混乱,这是someobject的类是什么样的样本:
public class SomeClass
{
private ExternalServer someServerOverTheNetwork = new ExternalServer();
public event EventHandler AsyncActionDone;
public Data SomeData { get; set; }
public void PerformAsyncAction()
{
someServerOverTheNetwork.GetSomeData(OnDataRetrived);
}
public Data OnDataRetrived(Data someData)
{
AsyncActionDone(this, new DataEventArgs(someData));
}
}
Run Code Online (Sandbox Code Playgroud)
我会考虑在执行异步操作的对象中实现异步设计模式。
public object Operation(object arg)
{
var ar = BeginOperation(arg, null, null);
return EndOperation(ar);
}
public IAsyncResult BeginOperation(object arg, AsyncCallback asyncCallback, object state)
{
AsyncResult asyncResult = new AsyncResult(asyncCallback, state);
// Lauch the asynchronous operation
return asyncResult;
}
private void LaunchOperation(AsyncResult asyncResult)
{
// Do something asynchronously and call OnOperationFinished when finished
}
private void OnOperationFinished(AsyncResult asyncResult, object result)
{
asyncResult.Complete(result);
}
public object EndOperation(IAsyncResult asyncResult)
{
AsyncResult ar = (AsyncResult)asyncResult;
return ar.EndInvoke();
}
Run Code Online (Sandbox Code Playgroud)
通过这种模式,您可以灵活地在对象上进行多个并发异步操作。
注意:您可以在网络上轻松找到通用 AsyncResult 类的实现。
编辑:
由于您想保留当前的设计,如果您的所有对象只能有一个异步操作,那么您可以定义一个 IAsyncOperation 接口并在所有对象中实现它。
public interface IAsyncOperation
{
event EventHandler AsyncActionDone;
void PerformAsyncAction();
}
Run Code Online (Sandbox Code Playgroud)
那么你可以:
public static CallSynchronously(IAsyncOperation asyncOperation)
{
ManualResetEvent reset = new ManualResetEvent(false);
asyncOperation.AsyncActionDone += (sender, args) => reset.Set();
asyncOperation.PerformAsyncAction();
reset.WaitOne();
}
Run Code Online (Sandbox Code Playgroud)
如果你的对象可以包含多个异步操作,那么如果没有反射,我认为没有办法实现你想要做的事情,但你仍然可以定义包装ManualResetEvent的所有异步操作的同步版本。
public void PerformAction()
{
ManualResetEvent reset = new ManualResetEvent(false);
this.AsyncActionDone += (sender, args) => reset.Set();
this.PerformAsyncAction();
reset.WaitOne();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4307 次 |
| 最近记录: |