好吧,所以基本上我有很多工(10),我想同時啟動所有任務並等待它们完成.完成後,我想執行其他任務.我讀了很多有關此的資源,但是我無法针對我的具體情况...
這是我目前拥有的(代碼已簡化):
public async Task RunTasks()
{
var tasks = new List<Task>
{
new Task(async () => await DoWork()),
//and so on with the other 9 similar tasks
}
Parallel.ForEach(tasks, task =>
{
task.Start();
});
Task.WhenAll(tasks).ContinueWith(done =>
{
//Run the other tasks
});
}
//This function perform some I/O operations
public async Task DoWork()
{
var results = await GetDataFromDatabaseAsync();
foreach (var result in results)
{
await ReadFromNetwork(result.Url);
}
}
所以我的問题是,当我等待任務完成時,
呼叫,它告诉我所有任務都結束了,即使它们都没有完成.我尝試添加
WhenAll
在我的飞天
当我輸入繼續任務時,資料不斷从我以前的
Console.WriteLine
中輸入
尚未真正完成。
我在這裏做什麼錯了?
foreach
- 5月前1 #
- 5月前2 #
本質上,您是在混合两種不相容的異步範例; 即
Parallel.ForEach()
和async-await
對於您想要的,執行一項或另一項.例如.你可以只用
Parallel.For[Each]()
並完全删除異步等待.Parallel.For[Each]()
仅在所有並行任務完成後才返迴,然後您可以移至其他任務。代碼也有其他一些問题:
you mark the method async but don't await in it (the await you do have is in the delegate, not the method);
you almost certainly want
p.ConfigureAwait(false)
隨時待命,特別是如果您不想立即在UI執行緒中使用結果。如果要使用TPL在不同的執行緒中並行執行這些任務,則可能需要這樣的东西:
public async Task RunTasks() { var tasks = new List<Func<Task>> { DoWork, //... }; await Task.WhenAll(tasks.AsParallel().Select(async task => await task())); //Run the other tasks }
這些方法仅並行處理少量代碼:將方法排队到執行緒池中以及返迴未完成的
Task
.同樣,對於如此少量的任務,並行化可能比異步執行花费更多的時間.仅当您的任務在第一次等待之前做一些更长的(同步)工作時,這才有意義。在大多數情况下,更好的方法是:
public async Task RunTasks() { await Task.WhenAll(new [] { DoWork(), //... }); //Run the other tasks }
在您的代碼中,我认為:
您不應將代碼包裝在
Task
中 在傳遞到Parallel.ForEach
之前您可以
await
Task.WhenAll
而不是使用ContinueWith
- 5月前3 #
DoWork
method是異步I / O方法.這意味着您不需要多个執行緒来執行其中的几个執行緒,因為在大多數情况下,该方法將異步等待I / O完成.一个執行緒就足以做到這一點。public async Task RunTasks() { var tasks = new List<Task> { DoWork(), //and so on with the other 9 similar tasks }; await Task.WhenAll(tasks); //Run the other tasks }
几乎不應该使用
Task
構造函式来建立新任務.要建立異步I / O任務,只需呼叫async
方法.要建立將線上程池執行緒上執行的任務,請使用Task.Run
.您可以阅讀這篇文章,详细了解Task.Run
以及建立任務的其他選項。 - 5月前4 #
還可以在Task.whenAll
週圍添加一个try-catch塊。NB:丟擲System.AggregateException的一个例項,该例項充当已發生的一个或多个異常的包裝.這對於協調多个任務(例如Task.waitAll()和Task.waitAny())的方法很重要,以便AggregateException能够將所有異常包裝在已發生的執行任務中。
try { Task.WaitAll(tasks.ToArray()); } catch(AggregateException ex) { foreach (Exception inner in ex.InnerExceptions) { Console.WriteLine(String.Format("Exception type {0} from {1}", inner.GetType(), inner.Source)); } }
相似問題
- c#:获取windows 8自動颜色主题的活動颜色c#netwpfwinapiwindows82021-01-12 01:28
- c#:遍歷函式結果時,foreach如何工作?c#netforeach2021-01-11 17:26
- c#:PictureBox問题c#netwinformspicturebox2021-01-11 04:56
- c#:靜態和例項方法同名?c#netoop2021-01-11 05:55
- c#:RequestUrlReferrer為空?c#netvisualstudiovisualstudio20082021-01-11 07:24
您几乎永远都不要使用
Task
直接構造函式.對於您而言,该任務只会觸發您迫不及待的實際任務。您可以簡單地致電
DoWork
然後取迴任務,將其儲存在列表中,然後等待所有任務完成.含義:但是,異步方法將同步執行,直到第一次等待未完成的任務.如果您担心该部分花费的時間太长,請使用
Task.Run
將其卸載到另一个ThreadPool
執行緒,然後儲存 that 列表中的任務: