Является ли EndInvoke () необязательным, сортирующим или необязательным? - PullRequest
56 голосов
/ 10 февраля 2009

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

Ответы [ 7 ]

53 голосов
/ 10 февраля 2009

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

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

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

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

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

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

18 голосов
/ 10 февраля 2009

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

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

9 голосов
/ 10 февраля 2009

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

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

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

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

4 голосов
/ 10 февраля 2009

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

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

3 голосов
/ 10 февраля 2009

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

2 голосов
/ 18 декабря 2012

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

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

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

2 голосов
/ 10 февраля 2009

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

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