簡體   English   中英

如何正確使用Async,Await和ManualResetEvents控制無限的while循環

[英]How to properly use Async, Await and ManualResetEvents to control an infinite while loop

所以我想在這里做的是:

  1. 如果隊列不為空,則使引擎循環並在對象上工作。
  2. 如果隊列為空,我調用manualresetevent使線程進入睡眠狀態。
  3. 當添加項目並且循環未激活時,我設置了manualresetevent。
  4. 為了使其更快,我從列表中挑選了最多5個項目,並對它們進行異步操作,並等待所有項目完成。

問題:

  1. 調用AddToUpdateQueueMethod的新調用后,即會立即調用兩個列表中的clear方法。
  2. 在我的腦海中,我正在等待Task.WhenAll(tasks),因此線程應在繼續操作之前等待其完成,因此,僅在Task.WhenAll(tasks)返回之后才應調用列表上的clear。

我在這里缺少什么,或者將是實現此目標的更好方法。

    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 Dataflow。 它是TPL之上的actor框架,具有async支持。 使用具有async操作且MaxDegreeOfParallelism為5的ActionBlock

var block = new ActionBlock<Content>(
    async content => 
    {
        var tasks = interactionProviders.
            Where(provider => provider.IsServiceSupported(content.ServiceType)).
            Select(provider => provider.UpdateThumbnail(content));
        await Task.WhenAll(tasks);

        if (content.ThumbnailLink != null && !content.ThumbnailLink.Equals(
            content.FileIconLink, 
            StringComparison.CurrentCultureIgnoreCase))
        {
            await DownloadAndUpdateThumbnailCache(content);
        }
    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5});

foreach (var content in GetContent())
{
    block.Post(content);
}

block.Complete();
await block.Completion

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM