我原本以为我对async
/await
和Task.Run()
非常了解,直到我遇到了这个问题:
我正在使用RecyclerView
和ViewAdapter
编写一个Xamarin.Android应用程序。在我的OnBindViewHolder方法中,我尝试异步加载一些图片。
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
// Some logic here
Task.Run(() => LoadImage(postInfo, holder, imageView).ConfigureAwait(false));
}
然后,在我的LoadImage函数中,我做了像这样的事情:
private async Task LoadImage(PostInfo postInfo, RecyclerView.ViewHolder holder, ImageView imageView)
{
var image = await loadImageAsync((Guid)postInfo.User.AvatarID, EImageSize.Small).ConfigureAwait(false);
var byteArray = await image.ReadAsByteArrayAsync().ConfigureAwait(false);
if(byteArray.Length == 0)
{
return;
}
var bitmap = await GetBitmapAsync(byteArray).ConfigureAwait(false);
imageView.SetImageBitmap(bitmap);
postInfo.User.AvatarImage = bitmap;
}
那些代码运行了。但为什么呢?
在将“配置等待”设置为false后,我学到的是代码不会在SynchronizationContext
(即UI线程)中运行。
如果我将OnBindViewHolder
方法设为async并使用await代替Task.Run,则代码会崩溃。
imageView.SetImageBitmap(bitmap);
说它不在UI线程中,这对我来说完全有意义。
那么为什么async
/await
代码崩溃而Task.Run()没有呢?
更新:答案
因为Task.Run没有被等待,所以抛出的异常没有显示。如果我等待Task.Run,就会出现我预期的错误。更多解释可以在下面的答案中找到。
imageView.SetImageBitmap(bitmap);
放入try/catch块中,您将找到相同的ex.Message
。这篇文章可能会引起兴趣(注意引用)。 - Funkawait
前后添加Debug.WriteLine($"thread: {System.Threading.Thread.Currentthread.Managedthreadid}")
。输出是什么? - noseratio - open to work