web-dev-qa-db-ja.com

非同期タスクと非同期void

これは非常に愚かな質問かもしれませんが、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_を使用すると、アプリケーションは_async Task_よりも約11秒速く画像(そのうちの29)を処理します。これはなぜでしょうか?

async voidasync void

非同期タスクasync task

メモリ使用量はvoidの方がはるかに多くなりますが、操作ははるかに速く完了します。私はスレッディングについてほとんど知識がありません。これが私がこの質問をしている理由です。なぜこれが起こっているのか誰かが説明できますか?

また、_async void_を使用するタイミングと使用しないタイミングについて調査しましたが、質問に対する回答が見つかりませんでした。 (私はちょうどよく検索しなかったかもしれません)。

ありがとうございました。

16
CareTaker22

async voidメソッドを呼び出すか、async Taskメソッドを待機せずに呼び出すと、メソッドが実際に完了するのを待たずに、コードはすぐに続行されます。これは、メソッドのいくつかの呼び出しが並列を実行している可能性があることを意味しますが、それらが実際にいつ完了するかはわかりません。

このように並列実行することで、すべての呼び出しが完了するのをTasksをコレクションに保存するしてからawait Task.WhenAll(tasks);

また、コードを並行して実行する場合は、安全に実行する必要があることにも注意してください。これは一般に「スレッドセーフ」と呼ばれます。

6
svick