我正在使用Flurl发出请求。目前,我有以下代码,并且一切正常:
public class Request()
{
public async Task<Bitmap> GetImage(string url)
{
using (var client = new Url(url)
{
var content = await client.GetStringAsync();
//return as image
}
}
}
在主UI线程上,我这样做:
public async void GetImages()
{
for (int i = 0; i < someCounter; i++)
{
var img = await myRequest.GetImage(url);
Thread.Sleep(100);
}
}
以上方法有效,但是UI线程休眠了一段时间,我想在一个任务中完成以上操作。所以我做到了:
public async void GetImages()
{
await Task.Run(async () =>
{
for (int i = 0; i < someCounter; i++)
{
var img = await myRequest.GetImage(url);
Thread.Sleep(100);
}
});
}
但是,使用上述方法,代码在await client.GetStringAsync();
处停止。也不例外,代码要么在那里停止执行,要么等待一些东西。
是我要尝试纠正的问题,还是有更好的方法?如果正确,为什么内部等待永远不会完成?
答案 0 :(得分:1)
不要使用Thread.Sleep(100);
,它不会await
,它不会把线程退回,它只会坐在那里什么都不做,并按住您的 UI
如果有的话,您应该使用Task.Delay
,它将与async
配合使用,不会阻塞 UI 线程,并且可以在 CallBack < / em>。
此外,您应该通过返回async
(并且仅使用await
),使async Task
async void
模式像病毒一样传播到启动该事件的事件
public async Task GetImages()
{
for (int i = 0; i < someCounter; i++)
{
var img = await myRequest.GetImage(url);
// for your small wait.
await Task.Delay(100);
}
}
如果您担心所有状态机,则在某些情况下,您只能返回Task
而不返回await
。
此外,在您的基础库中,没有任何内容可以返回到捕获的上下文,因此适合调用ConfigureAwait(false);
,这会给您带来一点效率
var content = await client.GetStringAsync()
.ConfigureAwait(false);
答案 1 :(得分:1)
如果您想使用睡眠,则可能应该使用Task.Delay
。 post将为您提供有关何时使用Thread.Sleep
和何时使用Task.Delay
的更好的见解。
第二,在代码中,应执行以下操作,而不是等待和睡觉:
public async void GetImages()
{
var tasks = new List<Task>();
for (int i = 0; i < someCounter; i++)
{
tasks.Add(myRequest.GetImage(url));
}
await Task.WhenAll(tasks).ConfigureAwait(false);
}
在for
循环结束时注意WhenAll
调用,这将创建一个任务,该任务将在所有提供的任务完成时完成。
然后,ConfigureAwait(false)
告诉等待中您不需要在当前上下文上恢复(在这种情况下,“在当前上下文上”意味着“在UI线程上”)
第三,在您对该网址的调用中,将其更改为Task.Run
:
public class Request()
{
public async Task<Bitmap> GetImage(string url)
{
using (var client = new Url(url)
{
//return as image
var content = await Task.Run(() => client.GetStringAsync());
}
}
}
您使用Task.Run
来调用方法,而不是作为方法实现的一部分。