2012-05-25 2 views
2

Рассмотрите приведенный ниже код. Я не хочу создавать несколько экземпляров class Waiter. (Таким образом, я не могу использовать класс ManualResetEvent)Threadpooling на одном экземпляре класса, как дождаться завершения всех потоков?

using System; 
using System.Threading; 

    public class Waiter 
    { 
     static int counter=0; 
     static int max=20; 

     public void Start() 
     { 
      for (int i = 1; i <= max; i++) 
      { 
       ThreadPool.QueueUserWorkItem(DoWork, (object)i); 

      } 
      Console.Read();//without this line the application quits before all threads are complete :(

     } 

     public void DoWork(object o) 
     { 
      try 
      { 
       Thread.Sleep(1000); 

      } 
      finally 
      { 
       counter++; 
       Console.WriteLine(counter); 
       if (counter==max) 
       { 
        Console.WriteLine("All threads complete"); 
       } 
      } 



     } 

    } 

    public class ThreadPoolExample 
    { 
     static void Main() 
     { 

      Waiter wtr=new Waiter(); 
      wtr.Start(); 



     } 
    } 

У меня есть две проблемы с кодом выше

1> Без Console.Read() приложение завершает работу, прежде всего нитками конца.

2> Заявление Console.WriteLine("All threads complete"); выполняет два раза.

Как исправить это?

ответ

3

Используйте Tasks вместо этого, и после этого вы можете сделать Task.WaitAll(tasks);

Кроме того, экземпляр ваши задачи через фабрику:

Task.Factory.StartNew(() => { Console.Writeline(""); }); 

Он будет использовать пул потоков для вас.

0

Вы должны использовать Interlocked.Increment для увеличения. counter. Так как есть условие гонки, когда два потока пытаются увеличить его одновременно.

Если вы хотите, чтобы несколько экземпляров Writer работали одновременно, вы не можете иметь статическую переменную counter. Они будут сражаться друг с другом. Просто сделайте это переменной частного экземпляра, и все будет хорошо. Макс должен либо быть const, либо readonly (и оставаться статичным), если он никогда не изменяется, или он также должен быть полем экземпляра, если он может измениться.

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

Смежные вопросы