收集下一个元素

时间:2014-12-26 19:28:35

标签: c# collections backgroundworker

我有一种下载图片的方法,要下载的图片列表以及多个后台工作人员。

我现在已经解决了这个问题,我将我的收藏分成两部分,并与每个后台工作人员进行交流。

我的问题是,我怎样才能让2个或更多背景工作者从同一个系列中拉出来,而不会相互踩踏。

List<string> Urls = new List<string>(Pretend I Added 50 URL'S);
List<string> Urls1 = new List<string>();
List<string> Urls1 = new List<string>();

Urls1.Add(Urls.GetRange(0,25);
Url2.Add(Urls.GetRange(26,50);

BackgroundWorker bwImageDownload1 = new BackgroundWorker();

        bwImageDownload1.DoWork += delegate(object sender, DoWorkEventArgs e)
        {
            foreach(string item in Urls1.Items)
            {
              DownloadPicture(item);
            }
        };


        bwImageDownload1.RunWorkerAsync();

BackgroundWorker bwImageDownload2 = new BackgroundWorker();

        bwImageDownload2.DoWork += delegate(object sender, DoWorkEventArgs e)
        {
            foreach(string item in Urls2.Items)
            {
              DownloadPicture(item);
            }
        };


        bwImageDownload2.RunWorkerAsync();

1 个答案:

答案 0 :(得分:3)

这是一种常见模式:n工作项需要同时由k工作者处理。 queue数据结构适用于此。

您可以使用多种队列(例如,对于更大,更常规的工作负载,您可能会考虑使用单独的message queue进程),但对于您的示例,可能只需使用像ConcurrentQueue这样的内存中队列。

ConcurrentQueue<string> urlQueue = new ConcurrentQueue<string>();
// ... fill it with the URLs ...

// Then, in your workers...
string url;
while (urlQueue.TryDequeue(out url)) {
    DownloadPicture(url);
}

ConcurrentQueue是线程安全的,因此在尝试从URL队列中出队时,它将确保两个工作人员不会互相踩到一起。


此外,与@SriramSakthivel一样,在.NET 4中,可以使用Task Parallel Library进行这些异步操作。实际上,您的整个示例可以简化为Parallel.ForEach(urlList, url => DownloadPicture(url));的单个调用(尽管您对操作的控制较少;对于更多控制,您可以直接使用Task。) / p>