所以我想在這裏做的是:如何正確使用異步,等待和ManualResetEvents控制的無限while循環
- 使發動機迴路和工作對象上,如果隊列不爲空。
- 如果隊列爲空,我調用manualresetevent使線程休眠。
- 當一個項目被添加,並且循環未激活時,我設置manualresetevent。
- 爲了讓它更快,我從列表中選取最多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 2015-02-12 04:48:22
您正在尋找的是['BlockingCollection'](https://msdn.microsoft.com/en-us/library/dd267312%28v=vs.110%29.aspx) –
2015-02-12 06:46:51