Я хотел бы рассмотреть реализацию Асинхронного шаблона проектирования в объектах, которые выполняют асинхронную операцию.
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();
}
С этим шаблоном вы можете иметь несколько одновременных асинхронных операций над вашим объектом.
Примечание. Вы можете легко найти реализацию универсального класса AsyncResult в Интернете.
Edit:
Поскольку вы хотите сохранить текущий дизайн, если весь ваш объект может иметь только одну асинхронную операцию, вы можете определить интерфейс IAsyncOperation и внедрить его во всех ваших объектах.
public interface IAsyncOperation
{
event EventHandler AsyncActionDone;
void PerformAsyncAction();
}
Тогда вы могли бы иметь:
public static CallSynchronously(IAsyncOperation asyncOperation)
{
ManualResetEvent reset = new ManualResetEvent(false);
asyncOperation.AsyncActionDone += (sender, args) => reset.Set();
asyncOperation.PerformAsyncAction();
reset.WaitOne();
}
Если ваши объекты могут содержать несколько асинхронных операций, то, не задумываясь, я думаю, что нет никакого способа достичь того, что вы хотите сделать, но вы все равно можете определить синхронную версию всех асинхронных операций, которая включает ManualResetEvent.
public void PerformAction()
{
ManualResetEvent reset = new ManualResetEvent(false);
this.AsyncActionDone += (sender, args) => reset.Set();
this.PerformAsyncAction();
reset.WaitOne();
}