Является ли функция EndInvoke() опциональной, необязательной или необязательной?

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

Ответ 1

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

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

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

Control.EndInvoke в порядке, чтобы игнорировать методы fire-and-forget - от msdn:

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

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