如何使用 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");
}
感谢大家分享知识。
我创建了一个自定义控件来显示图像。显示的图像必须从网站 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");
}
感谢大家分享知识。