2009-02-01 20 views
5
namespace ThPool 
{ 
    class Program 
    { 
     private static long val = 0; 
     private static string obj = string.Empty; 

     static void Main(string[] args) 
     { 
      Thread objThread1 = new Thread(new ThreadStart(IncrementValue)); 
      objThread1.Start(); 
      Thread objThread2 = new Thread(new ThreadStart(IncrementValue)); 
      objThread2.Start(); 
      objThread1.Join(); 
      objThread2.Join(); 

      Console.WriteLine("val=" + val + " however it should be " + (10000000 + 10000000)); 

      Console.ReadLine(); 
     } 

     private static void IncrementValue() 
     { 
      for (int i = 0; i < 10000000; i++) 
      { 
       Monitor.Enter(obj); 
       val++; 
       Monitor.Exit(obj); 
      } 
     } 
    } 
} 

Jak używać klasy ThreadPool w celu wymiany monitora wątku &?Sposób korzystania z klasy ThreadPool

+0

Hi Huda Czy możesz sformatować to trochę lepiej? –

+0

Pamiętaj, aby chronić wnętrze swoich metod roboczych za pomocą try-catch, ponieważ wyjątki w wątkach roboczych po prostu cicho zabijają wątek. –

Odpowiedz

1

Należy zajrzeć do ThreadPool.QueueUserWorkItem(). Zajmuje delegata, który jest uruchamiany w wątku wątku, przekazując obiekt stanu.

tj

string fullname = "Neil Barnwell"; 
ThreadPool.QueueUserWorkItem(state => 
{ 
    Console.WriteLine("Hello, " + (string)state); 
}, fullname); 

Nie należy mylić Control.BeginInvoke(). Spowoduje to przekazanie połączenia do wątku, który utworzył kontrolkę, aby zapobiec problemowi, w którym krzyżyki wywołują formanty aktualizacji. Jeśli potrzebujesz prostego wielowątkowości na formularzu Windows, spójrz na BackgroundWorker.

2
EventWaitHandle[] waitHandles = new EventWaitHandle[2]; 


for(int i = 0; i < 2; i++) 
{ 
    waitHandles[i] = new AutoResetEvent(false); 
    ThreadPool.QueueUserWorkItem(state => 
    { 
     EventWaitHandle handle = state as EventWaitHandle; 
     for(int j = 0; j < 10000000; j++) 
     { 
      Interlocked.Increment(ref val); //instead of Monitor 
     } 
     handle.Set(); 
    }, waitHandles[i]); 
} 

WaitHandle.WaitAll(waitHandles); 
Console.WriteLine("val=" + val + " however it should be " + (10000000 + 10000000)); 
4

Istnieje kilka sposobów korzystania z puli wątków. Do swojego zadania powinieneś przyjrzeć się poniższym.

  • Jeśli po prostu potrzebujesz zadania, aby uruchomić najprostszy sposób, należy użyć QueueUserWorkItem, który po prostu bierze delegata do uruchomienia. Wadą jest to, że masz niewielką kontrolę nad pracą. Delegat nie może zwrócić wartości i nie wiesz, kiedy bieg zostanie zakończony.
  • Jeśli chcesz trochę więcej kontroli, można użyć interfejsu BeginInvoke/EndInvoke delegatów. Spowoduje to uruchomienie kodu w wątku puli wątków. Możesz zapytać o status za pomocą instrukcji IAsyncResult zwróconej przez BeginInvoke i możesz uzyskać wynik (jak również każdy wyjątek w wątku roboczym) przez EndInvoke.

Aby użyć Enter/Exit na Monitor prawidłowo, trzeba się upewnić, że Exit jest zawsze nazywany. Dlatego powinieneś umieścić swoje wywołanie Exit w bloku finally.

Jednakże, jeśli nie trzeba podać wartość limitu czasu dla Enter, można byłoby o wiele lepiej po prostu za pomocą lock słowa kluczowego, który kompiluje się właściwy zestaw Enter i Exit połączeń.

+0

Możesz użyć AutoResetEvent lub ManualResetEvent, aby określić, kiedy bieg zostanie ukończony (jak w odpowiedzi pablito). – Cocowalla

0

Nie używaj nici do niczego poza najprostszymi rzeczami. W rzeczywistości niezwykle niebezpieczne jest uzyskanie blokady na wątku puli wątków. Możesz jednak bezpiecznie korzystać z Interlocked API.

Powiązane problemy