了解异步/等待和Task.Run() [英] Understanding async / await and Task.Run()

查看:72
本文介绍了了解异步/等待和Task.Run()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以为我很了解 async / await Task.Run(),直到遇到此问题为止:

I thought I understood async/await and Task.Run() quite well until I came upon this issue:

我正在使用 RecyclerView ViewAdapter 对Xamarin.Android应用进行编程.在我的 OnBindViewHolder 方法中,我试图异步加载一些图像

I'm programming a Xamarin.Android app using a RecyclerView with a ViewAdapter. In my OnBindViewHolder Method, I tried to async load some images

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
    // Some logic here

    Task.Run(() => LoadImage(postInfo, holder, imageView).ConfigureAwait(false)); 
}

然后,在我的 LoadImage 函数中,我做了类似的事情:

Then, in my LoadImage function I did something like:

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;
}

这些代码段有效.但为什么?

That pieces of code worked. But why?

我了解到的是,将configure await设置为false后,代码不会在 SynchronizationContext (这是UI线程)中运行.

What I've learned, after configure await is set to false, the code doesn't run in the SynchronizationContext (which is the UI thread).

如果我使 OnBindViewHolder 方法异步并使用await而不是Task.Run,​​则代码会在

If I make the OnBindViewHolder method async and use await instead of Task.Run, the code crashes on

imageView.SetImageBitmap(bitmap);

说它不在UI线程中,这对我来说完全有意义.

Saying that it's not in the UI thread, which makes totally sense to me.

那么为什么Task.Run()没有运行时, async / await 代码崩溃了?

So why does the async/await code crash while the Task.Run() doesn't?

更新:答案

由于未等待Task.Run,​​因此不会显示抛出的异常.如果我等待Task.Run,​​那是我所期望的错误.进一步的解释可以在下面的答案中找到.

Since the Task.Run was not awaited, the thrown exception was not shown. If I awaitet the Task.Run, there was the error i expected. Further explanations are found in the answers below.

推荐答案

这就像您不等待Task.Run一样简单,因此异常会被吞噬,并且不会返回到Task.Run的调用站点.

It's as simple as you not awaiting the Task.Run, so the exception gets eaten and not returned to the call site of Task.Run.

在Task.Run前面添加"await",您将获得异常.

Add "await" in front of the Task.Run, and you'll get the exception.

这不会使您的应用程序崩溃:

This will not crash your application:

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() => { throw new Exception("Hello");});
}

但是,这会使您的应用程序崩溃:

This however will crash your application:

private async void button1_Click(object sender, EventArgs e)
{
   await Task.Run(() => { throw new Exception("Hello");});
}

这篇关于了解异步/等待和Task.Run()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆