Завершить поток через интервал, если не возвращается - PullRequest
13 голосов
/ 21 декабря 2010

У меня есть поток, который получает некоторые данные из сети или последовательного порта.Поток должен завершиться (или вернуть false), если в течение 5 секунд не было получено никаких данных.

Другими словами, если работа потока занимает более 5 секунд, он должен остановиться.

Яписать на C #, но с любым языком .NET все в порядке.

Ответы [ 6 ]

8 голосов
/ 21 декабря 2010

Существует два подхода:

1.Инкапсулированное время ожидания

Поток, считывающий данные из сетевого или последовательного порта, может измерять время, прошедшее с момента его запуска, и ожидать данные не более, чем оставшееся время.Сетевые API-интерфейсы обычно предоставляют средства для указания таймаута для операции.Следовательно, выполняя простую DateTime арифметику, вы можете инкапсулировать управление временем ожидания в своем рабочем потоке.

2.Внешнее время ожидания

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

// start the worker thread
...

// give it no more than 5 seconds to execute
if (!workerThread.Join(new TimeSpan(0, 0, 5)))
{    
    workerThread.Abort();
}

Рекомендация: Я бы придерживался первого решения, так как оно ведет к более чистому и удобному в эксплуатации дизайну.Однако в определенных ситуациях может возникнуть необходимость обеспечить средства для «жесткого» прерывания таких рабочих потоков.

4 голосов
/ 21 декабря 2010

Любой механизм должен позволять вам указывать тайм-аут чтения. Например, вы можете установить NetworkStream.ReadTimeout до 5000 перед выполнением чтения. Вы должны быть в состоянии сделать что-то подобное для последовательных портов.

Чтение, для которого истекло время ожидания, вернет 0 из Stream.Read() - так вы можете узнать, действительно ли истекло время ожидания.

Обратите внимание, что использование Thread.Abort() устарело с .NET 2.0 для некоторых серьезных проблем, которые это может вызвать. Теоретически вы можете использовать Thread.Interrupt(), но это ничего не даст, если поток заблокирован в неуправляемом коде (включая ввод / вывод). Использование тайм-аутов чтения является правильным способом решения этой проблемы.

3 голосов
/ 21 декабря 2010

Если вы используете управляемый код для блокировки потока, вы можете использовать Thread.Abort, чтобы прервать выполнение. Если вы используете сторонний код или COM-взаимодействие, нет никакого способа прекратить выполнение потока. Единственный способ - установить Thread.isBackroundThread в значение true, а затем завершить процесс ...

2 голосов
/ 21 декабря 2010

Это решение с двумя потоками.

Пример:

Thread tParent = new Thread(new ThreadStart(() =>
{
    Thread t = new Thread(AsyncMethod);
    t.Start();
    Thread.Sleep(5000);
    if (t.IsAlive) t.Abort();
}));

Помните:

Использование такого метода - плохая практикаЗвонить Thread.Abort() не рекомендуется.Используйте Thread Synchronization, используя WaitHandles вместо этого.Например, AutoResetEvent.

2 голосов
/ 21 декабря 2010

Вы упомянули, что читаете из "сети". Если вы используете NetworkStream для чтения, вы можете указать ReadTimeout равным 5000 (это в миллисекундах). Это подождет 5 секунд, а затем вернется, если данные не были прочитаны Однако, если это находится в процессе или чтении, я думаю, что это могло бы возвратиться также, поэтому будьте осторожны. Я никогда ничего не делал с последовательным API, поэтому я не уверен, есть ли там такая настройка.

1 голос
/ 21 декабря 2010

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

Теперь, чтобы завершить поток, смотрите ответ alex, он просто прав!

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