C# 异步下载C语言中的文件

C# 异步下载C语言中的文件,c#,.net,task-parallel-library,async-await,C#,.net,Task Parallel Library,Async Await,我有一个关于C中异步操作的问题。假设我有一些类似的代码: public async void Download(string[] urls) { for(int i = 0; i < urls.Length; i++); { await DownloadHelper.DownloadAsync(urls[i], @"C:\" + i.ToString() + ".mp3"); } } 但这段代码实际上并不是异步下载文件。它开始从第一个URL下载文件

我有一个关于C中异步操作的问题。假设我有一些类似的代码:

public async void Download(string[] urls)
{
    for(int i = 0; i < urls.Length; i++);
    {
        await DownloadHelper.DownloadAsync(urls[i], @"C:\" + i.ToString() + ".mp3");
    }
}
但这段代码实际上并不是异步下载文件。它开始从第一个URL下载文件,然后等待此操作。然后它开始从第二个URL下载文件。。。等等

因此,文件被一个接一个地下载,我想让它们同时开始下载


我怎么做呢

不要等待单个任务,而是创建任务而不等待它们。将它们粘贴在列表中,然后等待任务。而不是等待任务

public async void Download(string[] urls)
{
    //you might want to raise the connection limit, 
    //in case these are all from a single host (defaults to 6 per host)
    foreach(var url in urls)
    {
        ServicePointManager
            .FindServicePoint(new Uri(url)).ConnectionLimit = 1000;
    }
    var tasks = urls
         .Select(url =>
             DownloadHelper.DownloadAsync(
                 url,
                 @"C:\" + i.ToString() + ".mp3"))
         .ToList();
    await Task.WhenAll(tasks);
}

与其等待单个任务,不如在不等待的情况下创建任务,将其粘贴在列表中,然后等待任务。而不是等待所有任务

public async void Download(string[] urls)
{
    //you might want to raise the connection limit, 
    //in case these are all from a single host (defaults to 6 per host)
    foreach(var url in urls)
    {
        ServicePointManager
            .FindServicePoint(new Uri(url)).ConnectionLimit = 1000;
    }
    var tasks = urls
         .Select(url =>
             DownloadHelper.DownloadAsync(
                 url,
                 @"C:\" + i.ToString() + ".mp3"))
         .ToList();
    await Task.WhenAll(tasks);
}

当你说异步是指并发时,它们是不同的。您可以使用Task.WhenAll同时等待所有异步操作:

public async Task Download(string[] urls)
{
    var tasks = new List<Task>();
    for(int i = 0; i < urls.Length; i++);
    {
        tasks.Add(DownloadHelper.DownloadAsync(urls[i], @"C:\" + i.ToString() + ".mp3"));
    }

    await Task.WhenAll(tasks);
}

您还应该避免使用async void,除非在事件处理程序中,当您说asynchronous是指concurrent时,它们是不同的。您可以使用Task.WhenAll同时等待所有异步操作:

public async Task Download(string[] urls)
{
    var tasks = new List<Task>();
    for(int i = 0; i < urls.Length; i++);
    {
        tasks.Add(DownloadHelper.DownloadAsync(urls[i], @"C:\" + i.ToString() + ".mp3"));
    }

    await Task.WhenAll(tasks);
}

您还应该避免使用async void,除非在事件处理程序中,我经常从async方法返回void,但前提是我将CancellationToken传递给async方法,即仍然有一个句柄指向被遗忘的对象method@spender但那个标记什么都没告诉你。您不知道操作是否结束或是否存在异常。。。让我们称之为坏习惯;非常感谢。真是太棒了!我经常从异步方法返回void,但只有当我将CancellationToken传递给异步方法时,也就是说,仍然有一个句柄指向被遗忘的对象method@spender但那个标记什么都没告诉你。您不知道操作是否结束或是否存在异常。。。让我们称之为坏习惯;非常感谢。真是太棒了!您真的不应该在这里执行AsyncVoid,因为我非常怀疑下载是一个事件处理程序。当您返回void时,没有可靠的方法可以通知您异常未受影响。只有AppDomain.UnhandledException或SynchronizationContext具有的任何特殊处理程序(如果有类似Application.UnhandledException的处理程序)才会捕获它,您真的不应该在这里执行async void,因为我非常怀疑下载是一个事件处理程序。当您返回void时,没有可靠的方法可以通知您异常未受影响。只有AppDomain.UnhandledException或SynchronizationContext具有的任何特殊处理程序(如果存在类似于Application.UnhandledException的处理程序)才会捕获它