Problem z działaniem asynchronicznej metody zwracającej Task w sposób synchroniczny

0

Po krótce chcę zaangażować metodę która wykonuje pewne działania do wykonywania w innym wątku(podobnie jak ThreadPool)

Więc skleciłem to:


        public async Task<Bitmap[]> CutBoardAsync(ChessboardCorners corners, Bitmap bitmap, int setId, CancellationToken cancellationToken)
        {
            return await Task.Run(() =>
            {
#if DEBUG
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                Debug.WriteLine(String.Format("ImageProcessorService::CutBoard(...) stared with set: {0}", setId));
#endif

                var averageWidth = ((corners.topRight.X - corners.topLeft.X)) / 8;
                var averageHeight = ((corners.bottomLeft.Y - corners.topLeft.Y)) / 8;

                List<Bitmap> bitmapsPieces = new List<Bitmap>(64);

                //init bitmaps
                for(int i = 0; i < 64; i++)
                {
                    if (cancellationToken.IsCancellationRequested)
                        cancellationToken.ThrowIfCancellationRequested();

                    bitmapsPieces.Add(new Bitmap(averageWidth, averageHeight));
                }

                //process base bitmap
                for (int x = 0; x < 8; x++)
                {
                    for (int y = 0; y < 8; y++)
                    {
                        if (cancellationToken.IsCancellationRequested)
                            cancellationToken.ThrowIfCancellationRequested();

                        var imgIndex = (x * 8) + y;

                        var tempGraphics = Graphics.FromImage(bitmapsPieces[imgIndex]);

                        tempGraphics.DrawImage(
                            bitmap,
                            new Rectangle(0, 0, averageWidth, averageHeight),
                            new Rectangle(x * averageWidth, y * averageWidth, averageWidth, averageHeight),
                            GraphicsUnit.Pixel);

                        tempGraphics.Dispose();
                    }
                }
#if DEBUG
                stopwatch.Stop();

                Debug.WriteLine(String.Format("ImageProcessorService::CutBoard(...) image was sliced in {0}ms", stopwatch.ElapsedMilliseconds));
#endif

                return bitmapsPieces.ToArray();
            });
        }

I przy wywoływaniu z metody asynchronicznej z operatorem await zwraca wynik:

        async Task ExtractPiecesFromChessboard()
        {
            Bitmap bitmap = (Bitmap)System.Drawing.Image.FromFile(Path.Combine(GetExecutablePathDirectory(), "3.png"));
            var imageProcessorService = ServiceLocator.Resolve<IImageProcessorService>();
            var corners = await imageProcessorService.GetChessboardCornersAsync(bitmap);
            var images = await imageProcessorService.CutBoardAsync(corners, bitmap, 0, CancellationToken.None);
           .
           .
           .
       }

A przy wywoływaniu z metody synchronicznej z użyciem Result, widzę w oknie danych wyjściowych, że metoda prawie zakończyła działanie (następną operacją jest return ...) i zmienna nigdy nie inicjalizuje się. A wątek wykonujący zawiesza się w oczekiwaniu na wynik.

   var images = imageProcessorService.CutBoardAsync(corners, bitmap, 0, CancellationToken.None).Result;
1

Stawiam na to że to jest klasyczny deadlock, i że ten pierwszy await z CutBoardAsync (return await Task.Run(() =>) chce się synchronizować na kontekście na którym Ty zablokowałaś się czekając synchronicznie na wynik przez wywoływanie .Result., także dodałbym do niego ConfigureAwait(false)

1 użytkowników online, w tym zalogowanych: 0, gości: 1