假设我有10个项目(需要通过http协议获取它们),在代码中启动了N个任务来获取数据,每个任务按顺序获取10个项目。我把这些项目放在一个ConcurrentQueue<Item>
中。之后,这些项目将逐个在一个线程不安全的方法中进行处理。
async Task<Item> GetItemAsync()
{
//fetch one item from the internet
}
async Task DoWork()
{
var tasks = new List<Task>();
var items = new ConcurrentQueue<Item>();
var handles = new List<ManualResetEvent>();
for i 1 -> N
{
var handle = new ManualResetEvent(false);
handles.Add(handle);
tasks.Add(Task.Factory.StartNew(async delegate
{
for j 1 -> 10
{
var item = await GetItemAsync();
items.Enqueue(item);
}
handle.Set();
});
}
//begin to process the items when any handle is set
WaitHandle.WaitAny(handles);
while(true)
{
if (all handles are set && items collection is empty) //***
break;
//in another word: all tasks are really completed
while(items.TryDequeue(out item))
{
AThreadUnsafeMethod(item); //process items one by one
}
}
}
我不知道在标记为***
的语句中可以放什么if条件。我不能在这里使用Task.IsCompleted
属性,因为我在任务中使用了await
,所以任务很快就完成了。而一个bool[]
数组来表示任务是否执行完全看起来真的很丑,因为我认为ManualResetEvent可以完成同样的工作。有人能给我建议吗?