2010-06-14 3 views
0

Так что этот вопрос касается шаблона дизайна .Net IAsyncResult и необходимости вызова EndInvoke, как покрытый this вопросаДва вопроса по обеспечению EndInvoke() вызывается в списке IAsyncResult объекты

фона

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

Вопрос 1

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

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

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

Вопрос 2

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

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

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

ответ

1

Я пробовал бы ваши объекты IAsyncResult, обертывая каждый EndInvoke в try/catch, который хранит любое сгенерированное исключение где-то в другом месте. Затем, когда вы вызываете все EndInvoke, вы можете увидеть, сохранили ли вы какие-либо исключения и выбрали исключение 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

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

+0

Любые ссылки или примеры кода для этого? – RobV

+0

См. Раздел «Обертка APM операций в задаче» на этой странице MSDN (http://msdn.microsoft.com/en-us/library/dd997423.aspx). –

+0

Ах, .NET 4.0 не является вариантом, так как API должен оставаться на 3.5, поскольку мы создаем для MS и Mono и Mono 4.0 не достаточно стабильна, чтобы рассмотреть возможность перехода к этой миграции в это время – RobV

 Смежные вопросы

  • Нет связанных вопросов^_^