BlazorExtensions / Canvas

HTML5 Canvas API implementation for Microsoft Blazor
MIT License
614 stars 146 forks source link

Canvas does not draw with multiple async events waited on via Task.WhenAll #110

Open CornCobs opened 3 years ago

CornCobs commented 3 years ago

Blazor version: Blazor Server

I wish to create multiple drawing Task which I wait for all at once with Task.WhenAll like this:

    private async Task DrawStart((int X, int Y) centroid, IEnumerable<(int X, int Y, int Ix)> startPoints)
    {
        await _context.TranslateAsync(centroid.X, centroid.Y);
        await _context.SetFillStyleAsync("blue");
        await _context.FillRectAsync(centroid.X, centroid.Y, 10, 10);
        await _context.SetFillStyleAsync("green");

        // This only draws 1 green rect
        // var drawStartTasks = startPoints.Select(pt =>
        //     _context.FillRectAsync(pt.X, pt.Y, 5, 5));
        // await Task.WhenAll(drawStartTasks);

        // This draws all start points correctly
        foreach (var pt in startPoints)
        {
            await _context.FillRectAsync(pt.X, pt.Y, 5, 5);
        }
    }

Desired output (correctly given by the foreach loop):

image

Output with Task.WhenAll:

image

Adding a .ContinueWith(_ => Console.WriteLine($"Drew point {pt}")) to each task, it appears each Task does complete successfully. Thus I assume the problem is with the canvas and not Blazor.

mizrael commented 3 years ago

Blazor is (still) single-threaded, there's no support yet for UI-side async operations.

On Tue., May 25, 2021, 5:29 a.m. CornCobs, @.***> wrote:

Blazor version: Blazor Server

I wish to create multiple drawing Task which I wait for all at once with Task.WhenAll like this:

private async Task DrawStart((int X, int Y) centroid, IEnumerable<(int X, int Y, int Ix)> startPoints)
{
    await _context.TranslateAsync(centroid.X, centroid.Y);
    await _context.SetFillStyleAsync("blue");
    await _context.FillRectAsync(centroid.X, centroid.Y, 10, 10);
    await _context.SetFillStyleAsync("green");

    // This only draws 1 green rect
    // var drawStartTasks = startPoints.Select(pt =>
    //     _context.FillRectAsync(pt.X, pt.Y, 5, 5));
    // await Task.WhenAll(drawStartTasks);

    // This draws all start points correctly
    foreach (var pt in startPoints)
    {
        await _context.FillRectAsync(pt.X, pt.Y, 5, 5);
    }
}

Desired output (correctly given by the foreach loop):

[image: image] https://user-images.githubusercontent.com/28252911/119473800-17566900-bd7e-11eb-8889-34f5c2170c53.png

Output with Task.WhenAll:

[image: image] https://user-images.githubusercontent.com/28252911/119473983-4967cb00-bd7e-11eb-9bb4-a44834c7012f.png

Adding a .ContinueWith(_ => Console.WriteLine($"Drew point {pt}")) to each task, it appears each Task does complete successfully. Thus I assume the problem is with the canvas and not Blazor.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/BlazorExtensions/Canvas/issues/110, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAK52KCJCGDGG53TDM6ZPN3TPNUX7ANCNFSM45O5WN3A .

RChrisCoble commented 3 years ago

He called out "Blazor Server" in his original post. If he was using client the WaitAll() on Blazor client it would have hung completely.

mizrael commented 3 years ago

I missed the "Server" part in the original message, apologies.

However, since the code is running on the HTML canvas, I still suspect it's not doing back/forth with the server and it's trying to run all those tasks on the client instead.