2012-05-16 31 views
2

有兩個流,第一個顯示進程表,第二個流考慮它們的計數和顯示。最初推出的第一,那麼第二:如何使線程以正確的順序運行

Thread t1 = new Thread(tmh1.FillTable); 
Thread t2 = new Thread(tmh1.GetGeneralInfo); 
t1.Start(); 
t2.Start(); 

下面是在線程中運行的方法:

public void FillTable() 
{ 
    while (true) 
    { 
     lock (lockObj) 
     { 
      arr.Clear(); 
      arr.AddRange(Process.GetProcesses()); 
      TableFormatter.Line(); 
      TableFormatter.Row("Name", "ID", "threads quantity", "Start time"); 
      TableFormatter.Line(); 
      } 
      Thread.Sleep(interval); 
     } 
} 
public void GetGeneralInfo() 
{ 
    while (true) 
    { 
     lock (lockObj) 
     { 
      Console.WriteLine(arr.Count.ToString()); 
     } 
    Thread.Sleep(interval); 
    } 
} 

和結果:

0 
----------------------------------------------------------------------------- 
|  Name  |   ID  | threads quantity| Start time   | 
----------------------------------------------------------------------------- 

,但應該是如下:

----------------------------------------------------------------------------- 
|  Name  |   ID  | threads quantity| Start time   | 
----------------------------------------------------------------------------- 
**68** 

如何使踏板按正確的順序運行?

+9

如果您需要順序訂購,爲什麼使用線程? – basti

+1

這聽起來不正確!看來t2完全依賴於t1的輸出。這不是一個選擇並行化的任務。 –

+0

我需要流同步工作,但直到一個讀取ArrayList中的數據,另一個必須等​​待,只有當第一個讀取所有數據並顯示它們時,第二個線程纔會顯示一般信息。 – Creative

回答

6

線程應該並行運行。如果你想要執行第二個線程在第一個線程完成時執行的任務,只需讓第一個線程執行第二個任務即可。

您也可以使用Task Parallel Library的方法依次運行任務。

Task.Factory.StartNew(() => tmh1.FillTable()).ContinueWith(() => tmh1.GetGeneralInfo(), TaskScheduler.FromCurrentSynchronizationContext()); 
0

您可以使用重置事件(參見AutoResetEvent或ManualResetEvent在C#中)的信號。但在鎖中呼叫等待信號可能是危險的(例如,死鎖)

4

我會使用任務。例如:

Task.Factory.StartNew(tmh1.FillTable).ContinueWith(tmh1.GetGeneralInfo) 

雖然,目前還不清楚爲什麼你會想要兩個線程。以下內容也應該有效:

Thread t1 = new Thread(()=>{tmh1.FillTable; tmh1.GetGeneralInfo();}); 
t1.Start(); 
3

這段代碼很奇怪,很難確定爲什麼要創建2個相互運行的線程。

假設預期的效果運行在不同的時間兩件事情在不同的線程,這樣做最簡單的方式,假設你可以使用C#4是利用任務並行庫。其中的一個例子如下:

 Task.Factory 
      .StartNew(() => Console.WriteLine("This is the first")) 
      .ContinueWith(t => Console.WriteLine("This is the second")); 

     Console.ReadLine(); 

如果你想手動創建線程,你應該在

0

閱讀起來只會是你貼我不得不說的是,使用線程的代碼這裏毫無意義。我猜測它比你所呈現的還要多。也許你修整了你的代碼來做一個更小的帖子?

無論如何,需要最少量的調整和重構的解決方案是使用Monitor.PulseMonitor.Wait

public void FillTable() 
{ 
    while (true) 
    { 
     Thread.Sleep(interval); 
     lock (lockObj) 
     { 
      arr.Clear(); 
      arr.AddRange(Process.GetProcesses()); 
      TableFormatter.Line(); 
      TableFormatter.Row("Name", "ID", "threads quantity", "Start time"); 
      TableFormatter.Line(); 
      Monitor.Pulse(lockObj); 
      } 
     } 
} 

public void GetGeneralInfo() 
{ 
    while (true) 
    { 
     lock (lockObj) 
     { 
      Monitor.Wait(lockObj); 
      Console.WriteLine(arr.Count.ToString()); 
     } 
    } 
} 

還有其他技術可以使用。一種常見的方法是使用生產者 - 消費者模式。 BlockingCollection這個類很容易。

private BlockingCollection<Process[]> queue = new BlockingCollection<Process[]>(); 

public void FillTable() 
{ 
    while (true) 
    { 
     Thread.Sleep(interval); 
     queue.Add(Process.GetProcesses()); 
    } 
} 

public void GetGeneralInfo() 
{ 
    while (true) 
    { 
     Process[] processes = queue.Take(); 
     Console.WriteLine(processes.Length.ToString()); 
    } 
}