var arguments = new double[] { 1d, 2d, 3d };
var result = arguments.Select(arg => Math.Sqrt(arg));
現在想象一下,一個異步方法,而不是Math.Sqrt
(我不知道下面的方法是一個真正的async
方法,但它的行爲幾乎相當於一個)如何同步異步方法?
public void BeginSqrt(Action<double> callback, double argument)
{
Thread.Sleep(100);
callback(Math.Sqrt(argument));
}
有稱這樣的不正確的方式方法而不分割代碼。所以讓我們將這個異步方法與AutoResetEvent
同步。我創建了一個輔助類:
public class Synchronizer<T, TResult>
{
AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
TResult _result;
public TResult Execute(Action<Action<TResult>,T> beginMethod, T argument)
{
beginMethod(Callback, argument);
_autoResetEvent.WaitOne();
return _result;
}
void Callback(TResult result)
{
_result = result;
_autoResetEvent.Set();
}
}
有了這個類,我們可以:
var synchronizer = new Synchronizer<double, double>();
var result = arguments.Select(arg => synchronizer.Execute(BeginSqrt, arg));
這種解決方案我在幾分鐘內創建的,而我思考的問題。有一個本地的替代呢?我相信我的解決方案存在缺陷,因爲它錯過了一些鎖。有一個更可靠的圖書館來做到這一點?
如果我正確地讀取了你的代碼,'BeginSqrt'完全不會做任何異步操作。它只是將返回值傳遞給回調函數而不是返回值(「continuation passing style」)。你的'Synchronizer'基本上是一個將'BeginSqrt'變成常規方法的包裝器。沒有涉及到併發,所以不需要鎖。 – dtb 2009-11-21 18:05:24
@dtb您說得對,也許我應該將其更改爲一個真正的異步方法以進行澄清 – 2009-11-21 18:15:44