Скажем, у меня есть 10N элементов (мне нужно получить их по 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
}
}
}
Я не знаю, что, если условие может быть помещено в оператор, помеченный ***
. Я не могу использовать здесь свойство Task.IsCompleted
, потому что я использую в задаче await
, поэтому задача выполняется очень быстро. И bool[]
, указывающий, выполнена ли задача до конца, выглядит действительно уродливо, потому что я думаю, что ManualResetEvent может сделать ту же работу. Может ли кто-нибудь дать мне предложение?