Делегат. EndInvoke документируется как , тыс должна назвать это (т.е. необходимый - еще протекает, происходят) - от msdn:
Важное Примечание
, Неважно, какую технику Вы используете, всегда называйте EndInvoke для завершения асинхронного вызова.
Управление. EndInvoke в порядке для игнорирования для методов "выпустил-забыл" - от msdn:
можно назвать EndInvoke для получения возвращаемого значения от делегата, если neccesary, но это не требуется.
Однако - если Вы используете Delegate.BeginInvoke
и не хотите результат, рассматриваете использование ThreadPool.QueueUserWorkItem
вместо этого - он сделает жизнь намного легче, и избежит боли IAsyncResult
и т.д.
И вызов EndInvoke не является дополнительным вызовом, это - часть контракта. При вызове BeginInvoke, необходимо назвать EndInvoke.
Классический пример того, почему это необходимо. Очень возможно, что IAsyncResult, возвращенный из BeginInvoke, выделил ресурсы, присоединенные к нему. Обычно своего рода WaitHandle. Поскольку IAsyncResult не реализует IDisposable, другое место должно быть выбрано для освобождения ресурсов. Единственным местом, чтобы сделать так является EndInvoke.
я кратко обсуждаю эту проблему в следующем сообщении в блоге.
http://blogs.msdn.com/jaredpar/archive/2008/01/07/isynchronizeinvoke-now.aspx
Это не является дополнительным, потому что вызов BeginInvoke использует WaitHandle, который по очереди использует объект ядра, который поддерживает счет, сколько ссылки имеются к нему. Вызов EndInvoke корректно располагает дескриптор, который постепенно уменьшает тот счетчик на объекте ядра и когда то количество достигнет нуля, менеджер по объекту ядра уничтожит его.
EndInvoke не является дополнительным, потому что это - место, где исключения выдаются, если что-то пошло не так, как надо в асинхронной обработке.
Так или иначе не должно быть никакой утечки, потому что, если IAsyncResult содержит некоторый собственный ресурс, он должен правильно реализовать IDisposable и расположить такие ресурсы, когда GC называет его финализатор.
Ее единственное дополнительное, если Вы не возражаете против памяти своей программы, становящейся очень крупными. Проблема - то, что GC содержит на все ссылки в Вашем потоке, потому что Вы могли бы хотеть назвать EndInvoke в какой-то момент. Я пошел бы с ответом Marc, пул потоков сделает Вашу жизнь легче. Однако необходимо предостеречься при порождении потоков от потоков поскольку это ограничено в количестве потоков, которые это может вращать.