我有一种下载图片的方法,要下载的图片列表以及多个后台工作人员。
我现在已经解决了这个问题,我将我的收藏分成两部分,并与每个后台工作人员进行交流。
我的问题是,我怎样才能让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();
答案 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>