如何异步下载两个图像,只有在做某事后才能下载

时间:2014-01-14 08:58:49

标签: c# wpf asynchronous

我在WPF应用上使用VS2010。 我无法使用 async 功能。 基本上我需要加载两个图像,下载图像后需要打印它们。

我需要管理两个图像的下载。怎么做到这一点?

var bitmap = new BitmapImage(new Uri("http://abcd.com/logo.png"));
var bitmapB = new BitmapImage(new Uri("http://abcd.com/logoB.png"));    

if (!bitmap.IsDownloading)
{
    // print immediately code here
}
else
{
    bitmap.DownloadCompleted += (o, e) =>
    {
        // print when download completed
    };
}    

if (!bitmapB.IsDownloading)
{
    // print immediately
}
else
{
    bitmapB.DownloadCompleted += (o, e) =>
    {
        // print when download completed
    };
}

2 个答案:

答案 0 :(得分:2)

这听起来像你真正想要的是WebClient Class。您可以使用其多种方法将图像作为文件或byte集合下载。最好的部分是您也可以异步执行此操作,因此它将自动发生在后台线程上。

使用这些异步方法时,需要处理相关的Download...Completed事件以检索结果。来自MSDN上的DownloadStringCompletedEventHandler Event页:

public static void DownLoadFileInBackground2 (string address)
{
    WebClient client = new WebClient ();
    Uri uri = new Uri(address);

    // Specify that the DownloadFileCallback method gets called 
    // when the download completes.
    client.DownloadFileCompleted += new AsyncCompletedEventHandler(
DownloadFileCallback2);
    // Specify a progress notification handler.
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(
DownloadProgressCallback);
    client.DownloadFileAsync (uri, "serverdata.txt");
}

有关详细信息,请查看MSDN网站上的WebClient.DownloadDataAsync MethodWebClient.DownloadFileAsync Method页面。

答案 1 :(得分:1)

类似下面的代码应该为可变数量的图像执行任务。它在调用UI线程中的PrintImages方法之前,在ThreadPool线程中按顺序下载所有图像。请注意,下载后每个图像都被冻结(image.Freeze()),以使其可以跨线程访问。

private void DownloadAndPrintImagesAsync(IEnumerable<string> urls)
{
    ThreadPool.QueueUserWorkItem(o =>
    {
        var images = urls.Select(url => DownloadImage(url));

        Dispatcher.Invoke(new Action(() => PrintImages(images)));
    });
}

private BitmapImage DownloadImage(string url)
{
    var buffer = new WebClient().DownloadData(url);
    var image = new BitmapImage();

    using (var stream = new MemoryStream(buffer))
    {
        image.BeginInit();
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.StreamSource = stream;
        image.EndInit();
    }

    image.Freeze();
    return image;
}

private void PrintImages(IEnumerable<BitmapImage> images)
{
    // print here
}

您可以通过并行发出多个下载来改善这一点,但这会使代码复杂化。在打印之前,您必须等待所有异步下载完成。


更新:根据Sheridan提供的建议,您可以像这样修改DownloadAndPrintImagesAsync方法:

private List<BitmapImage> images = new List<BitmapImage>();

private void DownloadAndPrintImagesAsync(IEnumerable<string> urls)
{
    foreach (var url in urls)
    {
        var webClient = new WebClient();
        webClient.DownloadDataCompleted += ImageDownloadCompleted;
        webClient.DownloadDataAsync(new Uri(url));
    }
}

private void ImageDownloadCompleted(object sender, DownloadDataCompletedEventArgs e)
{
    if (!e.Cancelled && e.Error == null)
    {
        var image = new BitmapImage();

        using (var stream = new MemoryStream(e.Result))
        {
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.StreamSource = stream;
            image.EndInit();
        }

        images.Add(image);

        if (images.Count == 2) // or whatever
        {
            // print images
        }
    }
}