Так что я пытаюсь сделать здесь:Как правильно использовать Async, ОЖИДАНИЕ и ManualResetEvents контролировать бесконечное время цикла
- Сделайте петлю двигателя и работу на объекте, если очередь не пуста.
- Если очередь пуста, я вызываю handresetevent, чтобы поток был спящим.
- Когда элемент добавлен, и цикл не активен, я задал метод handresetevent.
- Чтобы ускорить работу, я забираю почти 5 элементов из списка и выполняю операцию на них асинхронно и жду, пока все они закончатся.
Проблема:
- Четкие методы на двух списках, называются как только новый вызов AddToUpdateQueueMethod называется.
- В моей голове, когда я жду Task.WhenAll (задачи), поэтому поток должен ждать своего завершения, прежде чем двигаться вперед, поэтому ясность в списках должна вызываться только после Task.WhenAll (задачи) возвращается.
Что мне здесь не хватает, или что будет лучшим способом достичь этого.
public async Task ThumbnailUpdaterEngine()
{
int count;
List<Task<bool>> tasks = new List<Task<bool>>();
List<Content> candidateContents = new List<Content>();
while (true)
{
for (int i = 0; i < 5; i++)
{
Content nextContent = GetNextFromInternalQueue();
if (nextContent == null)
break;
else
candidateContents.Add(nextContent);
}
foreach (var candidateContent in candidateContents)
{
foreach (var provider in interactionProviders)
{
if (provider.IsServiceSupported(candidateContent.ServiceType))
{
Task<bool> task = provider.UpdateThumbnail(candidateContent);
tasks.Add(task);
break;
}
}
}
var results = await Task.WhenAll(tasks);
tasks.Clear();
foreach (var candidateContent in candidateContents)
{
if (candidateContent.ThumbnailLink != null && !candidateContent.ThumbnailLink.Equals(candidateContent.FileIconLink, StringComparison.CurrentCultureIgnoreCase))
{
Task<bool> task = DownloadAndUpdateThumbnailCache(candidateContent);
tasks.Add(task);
}
}
await Task.WhenAll(tasks);
//Clean up for next time the loop comes in.
tasks.Clear();
candidateContents.Clear();
lock (syncObject)
{
count = internalQueue.Count;
if (count == 0)
{
isQueueControllerRunning = false;
monitorEvent.Reset();
}
}
await Task.Run(() => monitorEvent.WaitOne());
}
}
private Content GetNextFromInternalQueue()
{
lock (syncObject)
{
Content nextContent = null;
if (internalQueue.Count > 0)
{
nextContent = internalQueue[0];
internalQueue.Remove(nextContent);
}
return nextContent;
}
}
public void AddToUpdateQueue(Content content)
{
lock (syncObject)
{
internalQueue.Add(content);
if (!isQueueControllerRunning)
{
isQueueControllerRunning = true;
monitorEvent.Set();
}
}
}
С TPL, вы почти никогда не нужно использовать 'ManualResetEvent' и такие вещи, как такие вещи, как' Task.Run (() = > monitorEvent.WaitOne()) ', если вы не имеете дело с каким-то устаревшим кодом. Посмотрите на TPL Dataflow, он предлагает множество возможностей для организации обработки конвейера. – Noseratio
Что вы ищете, это ['BlockingCollection'] (https://msdn.microsoft.com/en-us/library/dd267312%28v=vs.110%29.aspx) –