【问题标题】:async Task vs async void异步任务与异步无效
【发布时间】:2017-12-06 14:46:49
【问题描述】:

这可能是一个非常愚蠢的问题,但我有以下代码行可以将 RAW 图像转换为 BitmapImages:

public async void CreateImageThumbnails(string imagePath, int imgId)
{
    await Task.Run(() => controlCollection.Where(x => x.ImageId == imgId).FirstOrDefault().ImageSource = ThumbnailCreator.CreateThumbnail(imagePath));
}

调用这个方法CreateThumbnail()

public static BitmapImage CreateThumbnail(string imagePath)
{
    var bitmap = new BitmapImage();

    using (var stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
    {
        bitmap.BeginInit();
        bitmap.DecodePixelWidth = 283;
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.StreamSource = stream;
        bitmap.EndInit();
    }

    bitmap.Freeze();

    GC.WaitForPendingFinalizers();
    GC.Collect();

    return bitmap;
}

当在我的CreateImageThumbnails 方法中使用async Void 而不是async Task 时,我的应用程序处理图像(其中29 个)比async Task 快大约11 秒。为什么会这样?

异步无效

异步任务

使用void 的内存使用量要多得多,但操作完成的速度要快得多。我对线程知之甚少,这就是我问这个问题的原因。有人能解释一下为什么会这样吗?

我还对何时以及何时不使用async void 进行了一些研究,但我找不到我的问题的答案。 (我可能只是没有很好地搜索)。

谢谢。

【问题讨论】:

  • 也许这会有所帮助:stackoverflow.com/questions/12144077
  • async void 是一劳永逸,所以没有任何东西跟踪异步操作(甚至确保它完全运行),而 async Task 实际上保留了一个可以等待的跟踪。跨度>
  • @Magnus 是的,当我使用Task 呼叫CreateImageThumbnails 时,我在等待。
  • 如果不等待,就和使用void一样。
  • 与问题无关,但请记住,如果在 controlCollection 中找不到匹配项,FirstOrDefault() 可能会抛出 NullReferenceException。如果你确定它不会发生,你仍然可以简化它调用controlCollection.First(x => x.ImageId == imgId).ImageSource = ...

标签: c# async-await task void


【解决方案1】:

当你调用一个async void方法,或者调用一个async Task方法而不等待它(如果被调用的方法包含一个await,所以它不会阻塞),你的代码将立即继续,无需等待方法才能真正完成。这意味着该方法的多个调用可以并行执行,但您不知道它们何时真正完成,您通常需要知道这一点。

您可以像这样利用并行执行,同时还可以通过Tasks 存储在集合中然后使用await Task.WhenAll(tasks); 来等待所有调用完成。

另外请记住,如果您想并行执行代码,您必须确保这样做是安全的。这通常称为“线程安全”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多