我有一個方法返回XML元素,但該方法需要一些時間才能完成並返回一個值。在c#中同時運行多個方法
我現在有什麼是
foreach (var t in s)
{
r.add(method(test));
}
但這只是前一個完成後運行的下一條語句。我怎樣才能讓它同時運行?
我有一個方法返回XML元素,但該方法需要一些時間才能完成並返回一個值。在c#中同時運行多個方法
我現在有什麼是
foreach (var t in s)
{
r.add(method(test));
}
但這只是前一個完成後運行的下一條語句。我怎樣才能讓它同時運行?
您應該能夠使用任務是:
//first start a task for each element in s, and add the tasks to the tasks collection
var tasks = new List<Task>();
foreach(var t in s)
{
tasks.Add(Task.Factory.StartNew(method(t)));
}
//then wait for all tasks to complete asyncronously
Task.WaitAll(tasks);
//then add the result of all the tasks to r in a treadsafe fashion
foreach(var task in tasks)
{
r.Add(task.Result);
}
編輯 有一些問題與上面的代碼。有關工作版本,請參閱下面的代碼。在這裏,我還重寫了使用LINQ進行可讀性問題的循環(並且在第一個循環的情況下,爲了避免在lambda表達式內引起問題,在t
上關閉)。
var tasks = s.Select(t => Task<int>.Factory.StartNew(() => method(t))).ToArray();
//then wait for all tasks to complete asyncronously
Task.WaitAll(tasks);
//then add the result of all the tasks to r in a treadsafe fashion
r = tasks.Select(task => task.Result).ToList();
錯誤'System.Threading.Tasks.TaskFactory.StartNew(System.Action)'的最佳重載方法匹配有一些無效參數\t我不斷收到有關tasks.Add(Task.Factory.StartNew(method(t ))); – ikel 2012-01-11 07:48:47
我看到的代碼存在一些問題。給我兩分鐘來爲你編輯它。 – 2012-01-11 08:19:24
ikel - 在那裏,看看我的編輯。代碼清理了一下:) – 2012-01-11 08:24:31
您可以使用Parallel.ForEach
這將利用多個線程並行執行執行。您必須確保所有調用的代碼都是線程安全的並且可以並行執行。
Parallel.ForEach(s, t => r.add(method(t));
這是新東西,以前從未使用過,我會試着回到這裏,非常感謝 – ikel 2012-01-11 06:44:36
這幾乎可以,但這裏的問題是r上的add方法(我期望r是List或類似的)不是線程安全的,並且從多個不同的線程**添加到List將會導致問題。 – 2012-01-11 06:45:35
從我看到你正在更新循環內的共享集合。這意味着如果您並行執行循環,則會發生數據競爭,因爲多個線程會同時嘗試更新未同步的集合(假設r
是List
或類似的東西),從而導致不一致的狀態。
並行執行正確,你將需要包裝的代碼段鎖語句中:
object locker = new object();
Parallel.Foreach (s,
t =>
{
lock(locker) r.add(method(t));
});
然而,這將使執行實際串口,因爲每個線程需要獲取鎖,兩個線程不能同時進行。
更好的解決方案是爲每個線程設置一個本地列表,將部分結果添加到該列表中,然後在所有線程完成時合併結果。可能@ØyvindKnobloch-Bråthen的第二個解決方案是最好的,假設method(t)
是這種情況下真正的CPU-Hog。
修改爲這個問題的正確答案 改變
tasks.Add(Task.Factory.StartNew(method(t);));
到
是'r'和'add'和'method'和'test'線程安全的? – Yahia 2012-01-11 08:25:46