Что произойдет, если асинхронный вызов делегата никогда не вернется? - PullRequest
17 голосов
/ 08 июня 2010

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

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

Так что произойдет, если истечет время ожидания?Мы (предположительно) не хотим вызывать EndInvoke, поскольку это будет блокировать.Код может продолжать делать «другие вещи», но мы что-нибудь слили?Есть ли какая-то плохая ветка где-то заблокированная в ожидании возврата, который никогда не случится?Неужели мы просочились в память о том, куда будет помещен результат, который никогда не вернется?

Ответы [ 3 ]

5 голосов
/ 08 июня 2010

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

Из должности:

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

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

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

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

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

4 голосов
/ 08 июня 2010

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

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

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

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

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

ссылка MSDN на асинхронный шаблон.

3 голосов
/ 08 июня 2010

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

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

...