如何使用 Tasks 在 WinForms 中异步地从 url 抓取图像

How to grab an image from url asynchronously in WinForms properly using Tasks

我创建了一个自定义控件来显示图像。显示的图像必须从网站 url 加载。我决定使用 Tasks 异步执行操作。这是因为我的程序运行过程中会加载很多图片。

public Image Image { 
    get => image;
    set {
        image = value;
        Refresh();
    }
}
private Image image;

public async void LoadImageAsync(string url)
{
    Image = await GetImageAsync(url);
}

private async Task<Image> GetImageAsync(string url)
{
    HttpWebRequest request = WebRequest.CreateHttp(url);
    var response = await request.GetResponseAsync();
    using (var stream = response.GetResponseStream()) {
        return Image.FromStream(stream);
    }
}

上面的代码是我当前的设置。 这是使用任务的正确方法吗?

我来自 JS 和 Promises,所以我从那里学到了我的知识。我测试了该方法,它在后台显示 运行 正确。结果图像成功更新 WinForms UI 并设置 Image 变量。

首先,当你有一个异步任务时,你不应该使用void关键字

其次,你不需要使用setter来刷新UI,也最好为图像使用不同的名称属性。

第三,我建议使用HttpClient而不是WebRequest

public Image MyImage { get; set; }

public async Task LoadImageAsync(string url)
{
    MyImage = await GetImageAsync(url);
    Refresh();
}
private async Task<Image> GetImageAsync(string url)
{
    var httpClint = new HttpClient();
    var imageBytes = await httpClint.GetStreamAsync(url);
    return Image.FromStream(imageBytes)
}

您使用得当。您的代码准确说明了 async/await 的预期用途:您可以像编写同步代码一样编写异步代码。您编写了易于阅读的代码,不会在等待响应时锁定您的 UI。那就是你的目标。

如果您还没有阅读过 Microsoft 在 Asynchronous programming with async and await

上的文档

请注意您对 HttpWebRequest 的使用。 The documentation 说:

Important

We don't recommend that you use HttpWebRequest for new development. Instead, use the System.Net.Http.HttpClient class.

如果您的代码已经写好,您可以保留它。我很确定 HttpClient 只是在后台使用 HttpWebRequest。但这是值得考虑的事情。

由于这是一个关于在 C# 中使用任务的最佳方法的问题,我根据其他答案的建议编译了我的代码的最终版本。

static readonly HttpClient client = new HttpClient();
public Image Image { 
    get => image;
    set {
        image = value;
        Refresh();
    }
}
private Image image;

public async void LoadImageAsync(string url)
{
    Image = await GetImageAsync(url);
}

private async Task<Image> GetImageAsync(string url)
{
    using (Stream stream = await client.GetStreamAsync(url)) {
        return Image.FromStream(stream);
    }
}

根据其他人的建议,这利用了 HttpClient class.

LoadImageAsync方法的执行示例:

void AnyMethodOrEventHandler()
{
    imageControlInstance.LoadImageAsync("http://someurl.com/image.jpg");
}

感谢大家分享知识。