从Url异步加载图像到PictureBox

4

我希望能在Windows窗体应用程序中从Web加载图像,一切都很好,代码也可以正常工作,但问题是应用程序会停止工作,直到加载完成。我希望能够在不等待加载的情况下查看和使用应用程序。

PictureBox img = new System.Windows.Forms.PictureBox();
var request = WebRequest.Create(ThumbnailUrl);

using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
    img.Image = Bitmap.FromStream(stream);
}

1
是时候研究一下 BackgroundWorkerasync 了。 - Jonathon Reinhart
谢谢,我现在开始搜索。 - ara
请在后台工作器的“DoWork”事件中执行此操作。 - Rahul
我觉得这篇文章很有用:任务的基础知识 - Thadeu Fernandes
2
PictireBox控件支持异步加载图像,您无需使用后台工作器或async/await。它还可以从URL加载图像,因此您无需使用Web请求。您只需使用PictureBoxLoadAsync方法或ImageLocation属性即可。WaitOnLoad属性的值应为false,这是默认值。请参见下面的答案。 - Reza Aghaei
显示剩余2条评论
2个回答

8
这里是解决方案:
public async Task<Image> GetImageAsync(string url)
{
    var tcs = new TaskCompletionSource<Image>();
    Image webImage = null;
    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
    request.Method = "GET";
    await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
        .ContinueWith(task =>
        {
            var webResponse = (HttpWebResponse) task.Result;
            Stream responseStream = webResponse.GetResponseStream();
            if (webResponse.ContentEncoding.ToLower().Contains("gzip"))
                responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
            else if (webResponse.ContentEncoding.ToLower().Contains("deflate"))
                responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);

            if (responseStream != null) webImage = Image.FromStream(responseStream);
            tcs.TrySetResult(webImage);
            webResponse.Close();
            responseStream.Close();
        });
    return tcs.Task.Result;
}

以下是调用上述解决方案的方法:

代码如下:

PictureBox img = new System.Windows.Forms.PictureBox();
var result = GetImageAsync(ThumbnailUrl);
result.ContinueWith(task =>
{
    img.Image = task.Result;
});

你是不是漏掉了类似 ')' 这样的东西,因为代码不起作用。 - ara
非常感谢,太棒了,谢谢你。 - ara
PictireBox 控件本身支持异步加载图像,您无需使用后台线程或 async/await。 您可以简单地使用 PictureBoxLoadAsync 方法。 - Reza Aghaei
1
@YasserBazrforoosh 为什么要使用 TCS 和 ContinueWith,而 async/await 已经可用了呢?var response= Task.Factory.FromAsync<WebResponse>(..) 将返回响应并回到 UI 线程。可以使用 ConfigureAwait(false) 来避免这种情况,例如允许在线程池线程中加载图像。不需要任何 ContinueWith() 调用。 - Panagiotis Kanavos
此外,检查流是否为GZip或Deflate流是无用的。只需将WebRequestAutomaticDecompression属性设置为true,一切都会自动处理。 - Jimi
显示剩余2条评论

8

PictureBox控件内置了异步加载图像的支持。您不需要使用BackgroundWorker或async/await。它还可以从URL加载图像,因此您不需要使用Web请求。

您可以简单地使用PictureBoxLoadAsync方法或ImageLocation属性。 WaitOnLoad属性的值应该是false,这是默认值。

pictureBox1.LoadAsync("https://istack.dev59.com/K4tAc.webp");

这相当于:

pictureBox1.ImageLocation = "https://istack.dev59.com/K4tAc.webp";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接