Что происходит, если асинхронный вызов делегата никогда не возвращается?

Я нашел достойно выглядящий пример того, как назвать делегата асинхронно с тайм-аутом... http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx. Таким образом, это использует WaitOne с тайм-аутом, чтобы определить, не возвращается ли вызов, прежде чем тайм-аут истекает.

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

Таким образом, что происходит, если тайм-аут ожидания истекает? Мы (по-видимому), не хотим называть EndInvoke, поскольку это заблокируется. Код может продолжить делать 'другие вещи', но мы пропустили что-нибудь? Там некоторый плохой поток где-нибудь заблокирован, ожидая возврата, это никогда не собирается происходить? Мы пропустили некоторую память, где result-that-will-never-return был помещенным?

17
задан RichardHowells 8 June 2010 в 15:38
поделиться

3 ответа

Я думаю, этот пост говорит об этом очень хорошо:

Из сообщения:

Вы не можете завершить выполнение асинхронного делегата, если это не ваш поток , но вы можете, если это так. Если вы используете общие методы типа BeginInvoke, вы получаете поток пула потоков, управляемый платформой. Если вы используете класс Thread (), вы получаете собственный поток для управления, запуска, приостановки и т. Д. По своему усмотрению.

Асинхронная разработка требует, чтобы один решал, кто будет управлять потоками. Множество различных методов, которые выполняются асинхронно, за кулисами используют потоки ThreadPool.

Поскольку вы не можете / не должны завершать поток пула потоков, вы должны разработать код для взаимодействия с потоком, чтобы он мог выйти. Примеры MSDN для компонента BackgroundWorker демонстрируют такой вид общения.

Иногда в вашем коде может быть блокировка потока, ожидающая ввода-вывода. Здесь вы обычно вместо этого используете ожидание с несколькими объектами, ожидая ввода-вывода или ManualResetEvent.

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

5
ответ дан 30 November 2019 в 14:28
поделиться

Вам нужно вызвать EndInvoke().

Вот ссылка, рассказывающая о том, что происходит с EndInvoke():

Является ли EndInvoke() необязательным, вроде как необязательным или определенно необязательным?

Вот ссылка на статью в принятом ответе.

Мы все говорили о технике "запустить и забыть" с асинхронным вызовом делегата на различных публичных форумах. Многие преподаватели DevelopMentor написали статьи и примеры кода, демонстрирующие эту технику, и мы все описывали ее в классе. И, конечно, к тому времени она уже была в книге Дона. Поэтому, когда Microsoft в конце концов вспомнила, что нужно сообщить внешнему миру, что эта техника на самом деле не является законной, это было довольно удивительно.

Ссылка на MSDN ссылка на асинхронный паттерн.

4
ответ дан 30 November 2019 в 14:28
поделиться

Произойдет утечка ресурсов, удерживаемых потоком. Будут различные части объектов удаленного взаимодействия .NET, такие как AsyncResult. Несколько неуправляемых дескрипторов, связанных с потоком. Все мелочи по сравнению с одним мегабайтом адресного пространства виртуальной памяти, которое вы утекаете, удерживаемым стеком потоков.

Вы не можете ни в коем случае прервать резьбу, утечка постоянная. Когда вам приходится иметь дело с таким плохо работающим кодом, ваш единственный хороший ресурс - запустить его в отдельном процессе, чтобы вы могли заставить Windows очистить шрапнель, когда вы стреляете процессу в голову с помощью Process.Kill (). Даже это не гарантируется, такие зависания, как правило, связаны с некорректной работой драйверов устройств. Process.Kill не прерывает поток драйвера устройства. Легко увидеть: попытка прервать процесс с помощью Taskmgr.exe оставит его запущенным с одним дескриптором. У вас есть надежда, если этого не произойдет.

3
ответ дан 30 November 2019 в 14:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: