Действительно ли Delegate.EndInvoke () необходим? - PullRequest
25 голосов
/ 03 января 2011

Я прочитал пару форумов и даже один или два вопроса о стековом потоке, в которых говорилось, что Delegate.EndInvoke необходим при использовании Delegate.BeginInvoke. Многие из статей, которые я читал, рассказывая об использовании BeginInvoke, не упоминали об использовании EndInvoke. Также я развернул производственный код, используя только BeginInvoke, и проблем с памятью, похоже, нет. Я использовал BeginInvoke, как правило, с потоками, которые меня не волнуют, когда они заканчивают работу и сколько времени они занимают.

Ответы [ 7 ]

43 голосов
/ 03 января 2011

Из статьи MSDN 'Асинхронный вызов синхронных методов' :

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

Теперь есть теория, а затем есть практика. Как и многие другие разработчики до вас, вы обнаружили, что часто можете игнорировать это задокументированное требование. Это может быть деталь реализации, действительно ли EndInvoke делает что-то абсолютно необходимое, чтобы предотвратить сбой вашего приложения, утечку памяти и т. Д. Но вот в чем дело: если это задокументированное требование, вам действительно следует это сделать . Это не просто теория; речь идет о защите себя в случае перемен.

Задокументировав это требование, разработчики этого механизма асинхронного вызова в основном предоставили себе свободу изменить способ, которым BeginInvoke и EndInvoke работают по линии связи так, чтобы, если имелась достаточная причина (например, повышение производительности) , EndInvoke может внезапно стать намного более необходимым. Предположим, что это внезапно приведет к тупику, если вы забудете об этом. Они уже укрылись, сказав всегда звоните EndInvoke; если ваше приложение перестает работать, потому что вы не выполнили это требование, ответственность лежит на вас.

Я не говорю, что это вероятный сценарий. Моя точка зрения заключается в том, что вы не должны - или, по крайней мере, я бы не - спросить: "Это действительно необходимо?" с менталитетом Если мне удастся избежать этого, тогда я , поскольку задокументировано , что вы должны это сделать.

11 голосов
/ 03 января 2011

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

Для поддержки EndInvoke предоставьте AsyncCallback, и в этом методе обратного вызова обязательно закройтеВызовите EndInvoke с блоком try / catch.

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

9 голосов
/ 03 января 2011

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

При поиске по ключевому слову я нашел хорошее обсуждение.1009 *It can but it won't necessarily. Technically there is no such thing as a memory leak in .NET. Eventually the memory will be reclaimed by the GC. The problem is that it might be around a long time. The reason that you should call EndInvoke is because the results of the invocation (even if there is no return value) must be cached by .NET until EndInvoke is called. For example if the invoked code throws an exception then the exception is cached in the invocation data. Until you call EndInvoke it remains in memory. After you call EndInvoke the memory can be released.

Вот ссылка ,

Другая ссылка

1 голос
/ 03 января 2011

Я использовал BeginInvoke, как правило, с потоками, которые меня не волнуют, когда они заканчивают работу и сколько времени они занимают.

Похоже, вам стоит подумать об использованиикласс Thread вместо асинхронных делегатов.

Если вас интересуют результаты или , обнаруживающие ошибки (которые требуют сортировки результатов / ошибок в исходном потоке), то вы можете использовать асинхронные делегаты, и в этом случае вам потребуется , потребуется EndInvoke.А еще лучше, используйте классы Task или Task<TResult>.

Если вы просто хотите выделить некоторую независимую операцию, то используйте класс Thread.

1 голос
/ 03 января 2011

Было задокументировано, что EndInvoke не требуется (не выделены неуправляемые ресурсы - при условии, что вы не ждете на IAsyncResult) при использовании BeginInvoke для выполнения действий в потоке GUI в WinForms применение.

Однако это конкретное исключение из общего правила: для каждого Begin<i>Operation</i> должно быть соответствующее End<i>Operation</i>. Как уже отмечалось в другом A здесь: если код доступа GUI может выдать, вам понадобится EndInvoke, чтобы получить исключение.

См. Здесь (вроде) официальное подтверждение: http://blogs.msdn.com/b/cbrumme/archive/2003/05/06/51385.aspx#51395 (это комментарий Криса Брамми 12 May 2003 5:50pm.

Дополнительно: Документация для Control.BeginInvoke включает это замечание:

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

Так что это официально: использование WinForm асинхронного делегата для выполнения действий в потоке GUI не требует EndInvoke (если только вам не нужно возвращаемое значение или возможное исключение, в любом случае рассмотрите возможность использования Invoke ** 1040).

1 голос
/ 03 января 2011

MSDN говорит, что важно вызвать EndInvoke:

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

0 голосов
/ 14 марта 2016

Из документации Windows Form на Control.BeginInvoke ()

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

Это частный случай асинхронного вызова Windows Form в потоке пользовательского интерфейса и это не относитсяв общем случае , но это может помочь тем, кто в этой ситуации.

...