2010-08-27 3 views
3

Я создаю мои темы, какМульти нить рабочий статус нить

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 и т.д ...), но я не могу узнать, сколько потоков работает. во время выполнения.

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

+0

Мне трудно представить себе приложение, в котором оптимальным будет 255 одинаковых потоков. Помните, что максимальное количество потоков, которые могут работать в системе в любой момент времени = количество независимых ядер процессора в вашем целевом оборудовании. fwiw это мой опыт (Win XP SP2), что создание потока завершается после 120 в одном процессе. Это было в тестовом приложении, реализованном с одним потоком для клиента приложения на основе сокетов. Ни в коем случае я не мог бы реализовать настоящий производственный код. –

+0

Я работаю над сетевым приложением, поэтому мои потоки проводят много времени. и я думаю, что это не перегрузка для процессора – Rapunzo

ответ

0

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

+0

, можете ли вы узнать, что такое «критическая секция, защищенная одна переменная»? и как я могу использовать – Rapunzo

+0

Вот несколько примеров и определений: http://en.wikipedia.org/wiki/Critical_section –

1

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

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

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

Можете ли вы подробнее рассказать о своих других требованиях?

+0

Я пробовал это, но блокировал прогресс. – Rapunzo

+0

@ Rapunzo - действительно, в этом суть. 'Thread.Join' - это блокирующий вызов, поэтому' Console.WriteLine' не будет выполняться до тех пор, пока все потоки не будут завершены. Вы можете запустить этот фрагмент кода в другом потоке с соответствующей синхронизацией на любом выбранном вами механизме уведомлений. Я использовал 'Console.WriteLine' здесь для простоты. –

1

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

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

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

+0

Можете ли вы объяснить метод async? – Rapunzo

+0

Вы вызываете свой метод, используя BeginInvoke(), а не вызываете его напрямую. – Jerome

1

Во-первых, я должен отметить, что создание 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, вы можете получить действительно простую реализацию на Joe Albahari's website.

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(); 
+0

- это countdownevent, определенный в .net 3.5? – Rapunzo

+0

Нет, я обновил свой ответ, включив ссылку с простой реализацией. –

1

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

Я недавно wrote a blog post Сравнение различных асинхронных подходов, перечисленных в списке от best (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); 
+0

Я пытаюсь добавить с помощью System.Threading.Tasks; в мой проект, но получите ошибку: Тип или имя пространства имен «Задачи» не существует в пространстве имен «System.Threading» (вам не хватает ссылки на сборку?) – Rapunzo

+0

Чтобы использовать класс 'Task', вам понадобится либо .NET 4.0 или [Rx library] (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx) для .NET 3.5. –

1

Добавить делегат 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); 
      } 
     } 

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

+0

спасибо за решение, но (activeThreads.Count == 0) не работает, он много работает, много раз он терпит неудачу! вот мой код if ((activeThreads.Count) == 0) { j ++; progressBar1.Value = 0; btnSearch.Enabled = true; } в этом случае прогрессbar1. значение получает 0 и много раз растет после gettin 0 снова. и я не могу убедиться, что из потоков сделано – Rapunzo

+0

@Rapunzo - что происходит, когда вы начинаете каждый поток, как только он создается, и начальные потоки заканчиваются до того, как начнутся последние потоки. Быстрый способ обойти это - переместить t.Start() во второй цикл, чтобы вы создали все из них, прежде чем запускать любой из них. Более элегантный подход состоит в том, чтобы помещать созданные потоки в очередь и читать их с использованием шаблона производителя-потребителя. Это также позволяет вам контролировать количество одновременных потоков. –