加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#Downloader:我应该使用Threads,BackgroundWorker还是ThreadPo

发布时间:2020-12-16 07:52:45 所属栏目:百科 来源:网络整理
导读:我正在用C#编写一个下载程序并停止了以下问题:我应该使用什么样的方法来并行化我的下载并更新我的GUI? 在我的第一次尝试中,我使用了4个线程,并且在每个线程完成时我开始了另一个:主要问题是我的cpu在每个新线程启动时都是100%. 谷歌搜索,我发现Backgroun
我正在用C#编写一个下载程序并停止了以下问题:我应该使用什么样的方法来并行化我的下载并更新我的GUI?

在我的第一次尝试中,我使用了4个线程,并且在每个线程完成时我开始了另一个:主要问题是我的cpu在每个新线程启动时都是100%.

谷歌搜索,我发现BackgroundWorker和ThreadPool的存在:声明我想用我正在下载的每个链接的进度更新我的GUI,什么是最好的解决方案?

1)创建4个不同的BackgroundWorker,附加到每个ProgressChanged事件,委托我的GUI中的函数来更新进度?

2)使用ThreadPool并将最大和最小线程数设置为相同的值?

如果我选择#2,当队列中没有更多线程时,是否会停止4个工作线程?它暂停了吗?由于我必须下载不同的链接列表(每个链接20个链接)并在完成一个链接时从一个链接移动到另一个链接,ThreadPool是否在每个列表之间启动和停止线程?

如果我想在live上更改工作线程的数量并决定使用ThreadPool,从10个线程更改为6,它是否会抛出异常并停止4个随机线程?

这是让我头疼的唯一部分.
我提前感谢你们每个人的答案.

解决方法

我建议使用WebClient.DownloadFileAsync.您可以进行多次下载,每次下载时都会引发DownloadProgressChanged事件,完成后会引发DownloadFileCompleted.

您可以通过使用带有信号量的队列来控制并发,或者,如果您使用的是.NET 4.0,则可以使用BlockingCollection.例如:

// Information used in callbacks.
class DownloadArgs
{
    public readonly string Url;
    public readonly string Filename;
    public readonly WebClient Client;
    public DownloadArgs(string u,string f,WebClient c)
    {
        Url = u;
        Filename = f;
        Client = c;
    }
}

const int MaxClients = 4;

// create a queue that allows the max items
BlockingCollection<WebClient> ClientQueue = new BlockingCollection<WebClient>(MaxClients);

// queue of urls to be downloaded (unbounded)
Queue<string> UrlQueue = new Queue<string>();

// create four WebClient instances and put them into the queue
for (int i = 0; i < MaxClients; ++i)
{
    var cli = new WebClient();
    cli.DownloadProgressChanged += DownloadProgressChanged;
    cli.DownloadFileCompleted += DownloadFileCompleted;
    ClientQueue.Add(cli);
}

// Fill the UrlQueue here

// Now go until the UrlQueue is empty
while (UrlQueue.Count > 0)
{
    WebClient cli = ClientQueue.Take(); // blocks if there is no client available
    string url = UrlQueue.Dequeue();
    string fname = CreateOutputFilename(url);  // or however you get the output file name
    cli.DownloadFileAsync(new Uri(url),fname,new DownloadArgs(url,cli));
}


void DownloadProgressChanged(object sender,DownloadProgressChangedEventArgs e)
{
    DownloadArgs args = (DownloadArgs)e.UserState;
    // Do status updates for this download
}

void DownloadFileCompleted(object sender,AsyncCompletedEventArgs e)
{
    DownloadArgs args = (DownloadArgs)e.UserState;
    // do whatever UI updates

    // now put this client back into the queue
    ClientQueue.Add(args.Client);
}

不需要显式管理线程或转到TPL.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读