Два вопроса о том, как EndInvoke () вызывается в списке объектов IAsyncResult - PullRequest
0 голосов
/ 14 июня 2010

Таким образом, этот вопрос касается шаблона проектирования .Net IAsyncResult и необходимости вызова EndInvoke, как описано в этом вопросе

Фон

У меня есть некоторый код, в котором я запускаю потенциально много асинхронных вызовов определенной функции, а затем жду завершения всех этих вызовов, прежде чем использовать EndInvoke() для возврата всех результатов.

Вопрос 1

Я не знаю, встречался ли какой-либо из вызовов с исключением, пока я не вызову EndInvoke(), и в случае, если исключение происходит в одном из вызовов, весь метод должен завершиться сбоем, и исключение будет включено в специфичный для API исключение и выбрасывание вверх.

Итак, мой первый вопрос: каков наилучший способ обеспечить правильное завершение оставшихся асинхронных вызовов?

Является ли блок finally, который вызывает EndInvoke() для оставшихся незавершенных вызовов (и игнорирует любые дальнейшие исключения), лучшим способом сделать это?

Вопрос 2

Во-вторых, когда я впервые запускаю все свои асинхронные вызовы, я затем вызываю WaitHandle.WaitAll() в массиве WaitHandle экземпляров, которые я получил из моих IAsyncResult экземпляров. У метода, который запускает все эти асинхронные вызовы, есть тайм-аут для соблюдения, поэтому я предоставляю это методу WaitAll(). Затем я проверяю, все ли вызовы завершены, если нет, то должен был быть достигнут тайм-аут, чтобы метод также завершился сбоем и выдал еще одно исключение, специфичное для API.

Итак, мой второй вопрос: что мне делать в этом случае?

Мне нужно позвонить EndInvoke(), чтобы завершить все эти асинхронные вызовы, прежде чем я выдам ошибку, но в то же время я не хочу, чтобы код зависал, так как EndInvoke() блокирует. Теоретически, по крайней мере, если время ожидания WaitAll() истекло, то все асинхронные вызовы должны были сами превысить тайм-аут и выдать исключения (таким образом, завершив вызов), поскольку они также управляются тайм-аутом, но этот тайм-аут потенциально отличается от основного таймаута

Ответы [ 2 ]

1 голос
/ 14 июня 2010

Я бы перебрал ваши IAsyncResult объекты, оборачивая каждый EndInvoke в попытку / уловку, которая хранит любое сгенерированное исключение где-то еще.Затем, когда вы вызываете все EndInvoke s, вы можете увидеть, сохранили ли вы какие-либо исключения, и, если так, сгенерировать исключение API.Что-то вроде:

var exs = new List<Exception>();

foreach (IAsyncResult iasr in asyncResults) {
    try {
        iasr.EndInvoke();
    }
    catch (Exception e) {
        exs.Add(e);
    }
}

if (exs.Count > 0) {
    throw new MyException(exs.ToReadOnly());
}
0 голосов
/ 14 июня 2010

Я рекомендую использовать Задачи вместо IAsyncResult, если это вообще возможно.Они имеют более приятную семантику «продолжения» и могут обернуть API IAsyncResult, вызывая EndInvoke для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...