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' не делает ничего асинхронно вообще. Он просто передает возвращаемое значение обратному вызову вместо его возврата («стиль продолжения прохождения»). Ваш «Синхронизатор» в основном представляет собой оболочку, которая возвращает «BeginSqrt» обратно в обычный метод. Нет параллелизма, поэтому никаких блокировок не требуется. – dtb
@dtb Вы правы, может быть, я должен изменить его на настоящий асинхронный метод для разъяснения –