it-swarm.com.ru

Является ли EndInvoke () необязательным, сортирующим или необязательным?

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

56
endian

Delegate.EndInvoke документируется как , вы должны называть это (т.е. необходимо, иначе происходят утечки) - из msdn :

Важное примечание

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

Control.EndInvoke можно игнорировать для методов запуска и забывания - from msdn :

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

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

53
Marc Gravell

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

Больше информации здесь

18
Luca Martinetti

И вызов EndInvoke не является дополнительным вызовом, он является частью договора. Если вы вызываете BeginInvoke, вы должны вызвать EndInvoke.

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

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

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

9
JaredPar

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

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

4
Maghis

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

3
James Alexander

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

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

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

2
Robert Oschler

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

2
Steve