如何使WebClient等到上次下载完成?

时间:2016-12-13 20:52:06

标签: c# async-await task webclient

我使用 public async Task<string> Download(string uri, string path) { if (uri == null) return; //manually wait for previous task to complete while (Client.IsBusy) { await Task.Delay(10); } await Client.DownloadFileTaskAsync(new Uri(absoluteUri), path); return path; } 方法下载文件。但是,当我在循环中执行它时,我得到一个异常,它告诉我不支持并发操作。我试着像这样修理它:

Client

有时它可以工作,当多次迭代不是很大(1-5),当它运行10次或更多次我得到这个错误。  WebClient这里是WebClient,我创建了一次。我不会在每次迭代时生成新的客户端,因为它会产生开销。 回到我说,如何让IsBusy等待上一次下载完成之前?另外一个问题是 public IEnumerable<Task<string>> GetPathById(IEnumerable<Photo> photos) { return photos?.Select( async photo => { var path = await Download(Uri, Path); return path; }); } 适用于少量下载的原因。 代码我使用:

public class DateTimeUtils {

    public enum Pattern{
        ISO_ZULU("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"),
        AMERICAN("MM-dd-yyyy"),
        UTC("yyyy-MM-dd'T'HH:mm:ssZ"),
        TIME_TRAVEL("yyyy-MM-dd HH:mm:ss"),
        MERIDIEM("a"),
        HOUR_MINUTES("h:mm"),
        MILITARY("HH:mm");

        private final String pattern;
        Pattern(String pattern){
            this.pattern = pattern;
        }
        public String toString(){
            return pattern;
        }
    }

    protected static final Log logger = LogFactory.getLog(DateTimeUtils.class);
    private static final String UTC_ZONE_ID = "Etc/UTC";
    private static final String DEFAULT_ZONE_ID = ZoneId.systemDefault().getId();

    public static String format(Pattern pattern, Date date){
        return format(pattern.toString(), date, false);
    }

    public static String format(Pattern pattern, Date date, boolean arcTimeZone){
        return format(pattern.toString(), date, arcTimeZone);
    }

    public static String format(String pattern, Date date, boolean arcTimeZone){
        ZoneId zoneId;
        if(arcTimeZone){
            zoneId = getTimeZone();
        }else{
            zoneId = ZoneId.of(UTC_ZONE_ID);
        }
        return DateTimeFormatter.ofPattern(pattern).withZone(zoneId).format(date.toInstant());
    }
}

我想下载很多文件,不要阻止我的Ui线程。也许有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:3)

你错过了许多帮助你的代码所以我写了这个快速的例子来向你展示我在想你可能想要尝试的东西。它在.NET Core中基本相同,只需为WebClient交换HttpClient。

    static void Main(string[] args)
{
    Task.Run(async () =>
    {
        var toDownload = new string[] { "http://google.com", "http://microsoft.com", "http://apple.com" };
        var client = new HttpClient();

        var downloadedItems = await DownloadItems(client, toDownload);

        Console.WriteLine("This is async");

        foreach (var item in downloadedItems)
        {
            Console.WriteLine(item);
        }

        Console.ReadLine();
    }).Wait();
}

static async Task<IEnumerable<string>> DownloadItems(HttpClient client, string[] uris)
{
    // This sets up each page to be downloaded using the same HttpClient.
    var items = new List<string>(); 
    foreach (var uri in uris)
    {
        var item = await Download(client, uri);
        items.Add(item);
    }
    return items;
}

static async Task<string> Download(HttpClient client, string uri)
{
    // This download the page and returns the content.
    if (string.IsNullOrEmpty(uri)) return null;

    var content = await client.GetStringAsync(uri);
    return content;
}
相关问题