【问题标题】:completely baffled by async / await完全被 async / await 搞糊涂了
【发布时间】:2013-12-31 03:24:08
【问题描述】:

好的,我正在开发一个小型 MP3 播放器应用程序。它使用 DataSet 来保存 MP3 文件信息。这个问题是关于如何异步加载我的数据集。我一直在阅读很多东西,并尝试了很多东西,但我就是不明白。我要做的就是进行一个长时间运行的数据集填充过程并使其异步。

一开始,我的 DataSet (LoadMusic) 方法如下所示:

public partial class dsMusicPlayer
{
    public void LoadMusic()
    { ... }
}

它扫描目录结构中的 MP3 文件,并用文件信息(标题、艺术家、专辑等)填充 DataSet。它可以工作,但需要一分钟左右的时间才能运行,并且会自然地阻止 UI。因此,异步的完美候选者。我像这样重写了我的加载方法(否则不改变实现):

public async void LoadMusicAsync()
{
}

我知道事情不会那么简单,但我会一步一步来。果然,我收到一个警告,说我的异步方法“缺少等待操作符”。我所做的所有阅读都显示在方法调用之前使用了“await”,因此我将原始方法的主体重构为一个虚拟私有方法,其唯一目的是允许在容器中使用“await”关键字/公共方法:

public async void LoadMusicAsync()
{
    await LoadMusicInner();
}

private void LoadMusicInner()
{
}

接下来我发现我不能“等待无效”。美好的。我将我的私有方法更改为

private Task LoadMusicInner()
{
}

但现在我收到错误消息“并非所有代码路径都返回一个值”——这是有道理的,因为返回类型是任务。这就是我觉得卡住的地方。我的方法一开始是无效的,因为它真的没有返回任何东西。我应该怎么做?

【问题讨论】:

  • 顺便说一句,我最终放弃了一个我理解的旧式 BackgroundWorker 对象,但我的问题仍然存在。
  • 有很多关于 async/await 基础的文章。
  • 我读了一小部分,但实际上什么也没有。

标签: .net asynchronous async-await c#-5.0


【解决方案1】:

如果您只想在后台线程上执行一些同步代码,那么在您的调用代码中,您可以执行以下操作:

await Task.Run(() => player.LoadMusic());

这需要您在调用async 的位置创建整个方法。如果它不是顶级事件处理程序,那么它应该是一个async Task 方法,它的调用者也应该是await,将async 一直传播到顶部。那么顶级事件处理程序应该是async void(几乎在其他任何地方都避免使用async void)。

如果您想让您的代码真正异步(即在执行 IO 时不阻塞线程),那么您需要通过将同步调用(如 reader.ReadLine())替换为它们的异步版本来实际更改 LoadMusic() 的实现(比如await reader.ReadLineAsync())。

【讨论】:

    【解决方案2】:

    它应该看起来更像这样:

    public async Task LoadMusicAsync()
    {
        await Task.Run(() => this.LoadMusicInner());
    }
    
    private void LoadMusicInner()
    {
        // Work here..
    }
    

    【讨论】:

    • 谢谢,还没有机会尝试,但我回家后会。
    • 大多数时候,它不应该是这样的。库方法不应使用 Task.Run() 来伪装异步。
    • @svick 可确定长度的异步任务是Task.Run 的可接受候选者。启动自己的线程是最终的最佳实践,但自定义调度程序(避免线程池线程)将提供相同的结果。最精简的解决方案是 TaskCreationOptions.LongRunning` - 它会导致默认调度程序在设置时避免使用线程池。 msdn.microsoft.com/en-us/library/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 2017-01-16
    • 2020-02-28
    • 2022-01-23
    • 2019-01-12
    • 1970-01-01
    • 2014-08-14
    相关资源
    最近更新 更多