Многопоточный статус рабочего потока - PullRequest
3 голосов
/ 27 августа 2010

Я создаю свои темы как

 for (int i = 0; i < threadCount; i++)
 {
     Searcher src = new Searcher(i, this);

     threads[i] = new Thread(new ThreadStart(src.getIpRange));
     threads[i].Name = string.Format(i.ToString());
  }

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

с threadCount (= 100, 150, 255 и т. Д.), Но я не могу узнать, сколько потоков работает. на время выполнения.

и я хочу контролировать, когда все потоки завершат свою работу. и дать мне сообщение типа "Все темы мертвы, задания завершены ..." как событие runWorkerCompleted backgroundWorker's

Ответы [ 6 ]

1 голос
/ 27 августа 2010

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

        Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();            

           for (int i = 0; i < threadCount; i++)
            {
                Searcher src = new Searcher(i, this);
                src.Done = new SearcherDoneDelegate(ThreadDone);
                threads[i] = new Thread(new ThreadStart(src.getIpRange));
                threads[i].Name = string.Format(i.ToString());
            }

            foreach (Thread t in threads)
            {
                lock (activeThreads)
                {
                    activeThreads.Add(t.ManagedThreadId, t);
                }
                t.Start();
            }


        }
        public void ThreadDone(int threadIdArg)
        {
            lock (activeThreads)
            {
                activeThreads.Remove(threadIdArg);
                if (activeThreads.Count == 0)
                {
                    // all done
                }
            }
        }

        public delegate void SearcherDoneDelegate(int threadIdArg);
        public static object locker = new object();



        public class Searcher
        {
            public SearcherDoneDelegate Done { get; set; }
            public void getIpRange()
            {
                Done(Thread.CurrentThread.ManagedThreadId);
            }
        }

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

1 голос
/ 27 августа 2010

Вы определенно хотите использовать класс Task для этого или концепцию более высокого уровня, такую ​​как Parallel.ForEach.Прямое использование класса Thread довольно болезненно.

Я недавно написал сообщение в блоге , сравнивая различные асинхронные подходы, перечисленные в порядке от лучшего (Task) к худшему (Thread).).

Вот пример использования Task, демонстрирующий, что вы хотели сделать:

// Start all tasks
var threads = new Task[threadCount];
for (int i = 0; i < threadCount; i++) 
{ 
  Searcher src = new Searcher(i, this); 
  threads[i] = Task.Factory.StartNew(src.getIpRange);
}

// How many are running right now?
var runningCount = threads.Count(x => x.Status == TaskStatus.Running);

// Register a callback when they have all completed (this does not block)
Task.Factory.ContinueWhenAll(threads, MyCallback);
1 голос
/ 27 августа 2010

Во-первых, я должен отметить, что создание потоков 100, 150, 255 и т. Д., Вероятно, не очень хорошая идея.Возможно, вам лучше использовать класс ThreadPool или Task (если вы используете .NET 4.0).Кроме того, есть два хорошо известных метода ожидания завершения всех потоков.

Присоединение к потоку.

Thread.Join блокирует до завершения целевого потока.

for (int i = 0; i < threadCount; i++) 
{ 
   Searcher src = new Searcher(i, this); 
   threads[i] = new Thread(new ThreadStart(src.getIpRange)); 
   threads[i].Name = string.Format(i.ToString()); 
} 

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

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

Использование CountdownEvent.

A CountdownEvent ожидает, пока его внутренний счетчик не достигнет нуля.Этот метод лучше подходит, если вы хотите использовать ThreadPool.Если вы не используете .NET 4.0, вы можете получить действительно простую реализацию на сайте Джо Албахари .

var finished = new CountdownEvent(1);

for (int i = 0; i < threadCount; i++) 
{ 
   finished.AddCount();
   Searcher src = new Searcher(i, this); 
   threads[i] = new Thread(
     () =>
     {
        try
        {
          src.getIpRange();
        }
        finally
        {
          finished.Signal();
        }
     }
   threads[i].Name = string.Format(i.ToString()); 
} 

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

finished.Signal();
finished.WaitOne();
1 голос
/ 27 августа 2010

Вы можете проверить ThreadState свойство Thread.

Может быть лучше использовать асинхронные методы. Это дает вам объект WaitHandle, и вы можете использовать WaitHandle.WaitAll, чтобы дождаться завершения всех ваших асинхронных методов.

Вот введение в асинхронное программирование: http://msdn.microsoft.com/en-us/library/aa719598%28v=VS.71%29.aspx

1 голос
/ 27 августа 2010

Определить, когда все потоки закончены, просто.

for (int i = 0; i < threadCount; i++)
{
    threads[i].Join();
}

Console.WriteLine("All threads are done!");

Можете ли вы уточнить другие ваши требования?

0 голосов
/ 27 августа 2010

Почему вы не можете использовать одну переменную, защищенную критическим разделом, для управления количеством активных потоков? Потоковая функция может изменить эту переменную (конечно, войдя в критическую секцию).

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