2012-03-27 97 views
1

我有一個對象「守則」的列表:執行線程的列表

List<Code> listCodes = new List<Code>(); 

我需要執行一個線程列表內的每個代碼,但我不知道該怎麼做,因爲我試着這樣做:

foreach(Code c in listCodes) 
{ 
    Thread tr = new Thread(delegate() { 
     Execute(c.CodeLine); 
    }); 
} 

這的foreach是一個計時器,因爲這些代碼會被執行所有的時間,但是當我做相同的代碼被執行,即使第一次執行了很多次沒有完成,如果代碼需要5秒的時間來執行和完成,並且定時器是500ms,它將被執行例如,如果我在5秒後禁用定時器10次,例如。

我想不出什麼來執行列表中的代碼,每個代碼在他們的線程中,但我想要執行代碼0的線程(例如),只有當它在執行後完成。

謝謝。

+1

計時器正在很醜陋。如前所述,沒有理由,你也可以在線程內循環,並使用ManualResetEvent來停止循環。 – 2012-03-27 02:38:41

回答

4

System.Threading.Monitor.TryEnter是完美的人選:

foreach(Code c in listCodes) { 
    Code a = c; 

    new Thread(delegate() { 
     if(Monitor.TryEnter(a)) { 
      Execute(a.CodeLine); 
      Monitor.Exit(a); 
     } 
    }) { IsBackground = true }.Start(); 
} 

它所做的是試圖獲取Code對象的排它鎖。如果它不能(即Code已經執行),那麼什麼都不會發生;否則,鎖被獲取,並在執行完成時釋放。

+0

在線程開始執行的時候不會釋放排它鎖嗎?控制權在Execute()後立即返回給調用者。 – 2012-03-27 01:18:52

+0

@EricJ:不,鎖定代碼在線程內,而不是循環。 – Ryan 2012-03-27 01:19:19

+0

LOL錯過了。所以現在習慣了TPL,我讀過了顯式的線程創建。 – 2012-03-27 01:22:48

0

您需要實際等待Thread s完成。你可以通過撥打電話Join

List<Thread> threads = new List<Threads>(); 

foreach(Code c in listCodes) 
{ 
    Thread tr = new Thread(delegate() { 
     Execute(c.CodeLine); 
    }); 
    threads.Add(tr); 
} 

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

這些都在你的外部計時器中。

+1

這將阻塞主線程,直到所有其他線程完成,這將需要在可以阻塞的線程上執行代碼線程。 – 2012-03-27 01:21:31

1

我認爲使用Thread這樣的效率很低,應該用Task代替。

在C#5,我會做這樣的:

private static async Task RunCode(Code code, TimeSpan delay) 
{ 
    while (!Stopped) 
    { 
     var delayTask = Task.Delay(delay); 

     Execute(code.CodeLine); 

     await delayTask; 
    } 
} 

然後啓動一次(即不在一個定時器):

foreach (Code c in listCodes) 
{ 
    Task.Run(() => RunCode(c, TimeSpan.FromMilliseconds(1000))); 
}