Это EndInvoke() необязательно, какой-то дополнительный, или не обязательно?


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

7 56

7 ответов:

делегат.EndInvoke документируется как назови это (т. е. необходимо-иначе утечки случаются) - от msdn:

Важное Замечание

независимо от того, какой метод вы используете, всегда вызывать EndInvoke для завершения асинхронный вызов.

управление.EndInvoke можно игнорировать для методов fire-and-forget-from msdn:

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

однако-если вы используете Delegate.BeginInvoke и не хотите результата, рассмотрите возможность использования ThreadPool.QueueUserWorkItem вместо этого - это сделает жизнь намного проще, и избежать боли IAsyncResult etc.

EndInvoke не является обязательным.

Подробнее здесь

и вызов EndInvoke не является необязательным вызовом, это часть контракта. Если вы вызываете BeginInvoke, вы должны вызвать EndInvoke.

классический пример того, почему это необходимо. Очень возможно, что iasyncresult, возвращенный из BeginInvoke, выделил ресурсы, прикрепленные к нему. Чаще всего это своего рода WaitHandle. Поскольку IAsyncResult не реализует IDisposable, необходимо выбрать другое место для освобождения ресурсов. Единственное место, чтобы сделать это EndInvoke.

я кратко обсуждаю эту проблему в следующем блоге.

http://blogs.msdn.com/jaredpar/archive/2008/01/07/isynchronizeinvoke-now.aspx

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

в любом случае не должно быть никакой утечки, потому что если IAsyncResult держит какой-то собственный ресурс, он должен правильно реализовать IDisposable и утилизировать такие ресурсы, когда GC вызывает его финализатор.

Это не является необязательным, потому что вызов BeginInvoke использует WaitHandle, который, в свою очередь, использует объект ядра, который поддерживает количество ссылок на него. Вызов EndInvoke изящно размещает дескриптор, который уменьшает этот счетчик на объекте ядра, и когда этот счетчик достигает нуля, диспетчер объектов ядра уничтожит его.

Это только необязательно, если вы не возражаете, что память вашей программы растет очень большой. Проблема в том, что GC удерживает все ссылки в вашем потоке, потому что вы можете захотеть вызвать EndInvoke в какой-то момент. Я бы пошел с ответом Марка, threadpool сделает вашу жизнь проще. Однако вам нужно следить, если вы создаете потоки из своих потоков, так как он ограничен количеством потоков, которые он может вращать.

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

"обратите внимание, что команда Windows Forms гарантирует, что вы можете использовать Control.BeginInvoke в "огонь и забыть" манере-т. е. никогда не вызывая EndInvoke. Это не относится к асинхронным вызовам в целом: обычно каждый BeginXXX должен иметь соответствующий вызов EndXXX, обычно в обратный звонок."

в чем разница между Invoke() и BeginInvoke()