Да, вам нужно позвонить EndInvoke
. Но вы не можете вызывать его в ситуации тайм-аута (иначе это может заблокировать операцию, нарушая цель асинхронного выполнения и тайм-аутов).
Один из вариантов - выбросить его в пул потоков. Вы можете передать AsyncWaitHandle
на ThreadPool.RegisterWaitForSingleObject
и получить обратный вызов EndInvoke
(обязательно перехватывая исключения). Однако этот подход не масштабируется (в любой момент времени в пуле потоков может быть только 64 дескриптора).
Лучшим вариантом является использование новой Task
абстракции в .NET 4.0 (также доступно в .NET 3.5, если вы используете Rx). С ним гораздо проще работать.