Прерывание нерабочего потока

У меня есть многопоточное приложение, написанное на С#, мой максимальный номер потока - 256, и это приложение получает счетчики производительности компьютеров в интервале IP (192.168.1.0 -192.168.205.255), оно отлично работает и переключается много раз в день. потому что я должен получить отчеты.

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

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

foreach(Thread t in threads)
{
   t.start(); -----> t.start(countdownParameter) etc....
}

Параметр обратного отсчета - это максимальное время жизни каждого потока. Это означает, что если поток не может достичь машины, он должен быть прерван. например 60 секунд.. нет не 256 машин, я имел в виду 256 потоков... около 5000 ip и 600 из них живы. поэтому я использую 256 потоков для чтения их значений. а другое дело петля. мой цикл работает, так как пока все ipies заканчиваются, он начинается с самого начала.


person Rapunzo    schedule 18.10.2010    source источник
comment
Я не понимаю - чего ты хочешь добиться здесь countdownParameter? Что значит одна машина держит нить? как это останавливает вашу программу от зацикливания? Публикация реального кода будет большим подспорьем в получении полезной обратной связи.   -  person Steve Townsend    schedule 19.10.2010
comment
У вас 256 машин? Или процессоры? Или реальные темы? Или что?   -  person Arafangion    schedule 19.10.2010
comment
@Arafangion - боялся спросить, но на первый взгляд похоже, что на каждый IP один поток   -  person Steve Townsend    schedule 19.10.2010
comment
Вам действительно следует подумать о преобразовании этого в асинхронную настройку, чтобы вы могли более эффективно использовать потоки и не попасть в сценарий, о котором вы публикуете, а поток занимает много времени, обрабатывая предоставленный объект. Есть ли причина, по которой вы работаете с потоками без использования потоков?   -  person Liam    schedule 19.10.2010
comment
извините, позвольте мне объяснить, параметр обратного отсчета - это максимальное время жизни каждого потока. Это означает, что если поток не может достичь машины, он должен быть прерван. например 60 секунд.. нет не 256 машин, я имел в виду 256 потоков... около 5000 ip и 600 из них живы. поэтому я использую 256 потоков для чтения их значений. а другой - петля. мой цикл работает, так как пока все ipies заканчиваются, он начинается с самого начала.   -  person Rapunzo    schedule 19.10.2010


Ответы (4)


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

foreach(Thread t in threads)
{
   t.Start();
}

TimeSpan timeOut = TimeSpan.FromSeconds(10);
foreach(Thread t in threads)
{
   if (!t.Join(timeOut))
   {
       // Still not complete after 10 seconds, abort
       t.Abort();
   }
}

Конечно, есть более элегантные способы сделать это, например, использовать WaitHandles с WaitAll метод (обратите внимание, что WaitAll ограничен 64 дескрипторами одновременно в большинстве реализаций и не работает в потоках STA, таких как поток пользовательского интерфейса)

person Thomas Levesque    schedule 18.10.2010
comment
Я попробовал этот код, но все потоки ждут завершения потока, созданного до него. и это не полезное решение. - person Rapunzo; 21.10.2010

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

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

person CodesInChaos    schedule 19.10.2010
comment
Я пытался контролировать рабочее время с помощью таймера, но он заблокировал мою работу. какое решение вы предлагаете? - person Rapunzo; 19.10.2010
comment
API сокетов обычно имеют параметр/свойство TimeOut для режима блокировки (например, SendTimeOut и ReceiveTimeOut в классе .net Socked) и способ входа в неблокирующий (= асинхронный) режим (свойство Blocking в Socket). - person CodesInChaos; 19.10.2010
comment
Уничтожение потока может легко повредить состояние домена приложения, возможно, это верно для потоков ОС, но я сомневаюсь, что прерывание управляемого потока будет иметь такой эффект... Я просто вызываю ThreadAbortException в прерванном потоке. - person Thomas Levesque; 21.10.2010

Обычно поток застревает на вызове блокировки (если, конечно, у вас нет ошибки, вызывающей бесконечный цикл). Вам нужно определить, какой вызов блокируется, и «ткнуть» его, чтобы разблокировать. Возможно, ваш поток ожидает внутри одного из ожидающих вызовов .NET BCL (WaitHandle.WaitOne и т. д.), и в этом случае вы можете использовать Thread.Interrupt, чтобы разблокировать его. Но в вашем случае более вероятно, что API, управляющий связью с удаленными компьютерами, завис. Иногда вы можете просто закрыть соединение из отдельного потока, и это разблокирует зависший метод (как в случае с классом Socket). Если ничего не помогает, вам, возможно, придется вернуться к последнему методу вызова Thread.Abort. Просто имейте в виду, что если вы прервете поток, он может повредить состояние домена приложения, в котором произошло прерывание, или даже самого процесса. В .NET 2.0 было добавлено множество возможностей, делающих прерывания намного более безопасными, чем раньше, но некоторый риск все же остается.

person Brian Gideon    schedule 19.10.2010

Вы можете использовать что-то вроде этого:

public static T Exec<T>(Func<t> F, int Timeout, out bool Completed)
{
    T result = default(T);
    Thread thread = new Thread(() => result = F());
    thread.Start();
    Completed = thread.Join(Timeout);
    if(!Completed) thread.Abort();
    return result;
}
person BrainMaxx    schedule 19.10.2010