Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Blazor Server - Modal cannot be closed in background thread #504

Open
HenryDeveloper opened this issue Mar 1, 2023 · 5 comments
Open
Labels
Bug Something isn't working Needs: More Information The author needs to provide more information on the issue.

Comments

@HenryDeveloper
Copy link

HenryDeveloper commented Mar 1, 2023

Describe the bug
I am working on a Blazor Server + RabbitMQ application (with Rebus package), when a new message arrives to the Consumer I need a modal to be opened and after the process is finished the modal is closed, the modal works perfectly when the method is called Modal.Show<DisplayMessage>() but doesn't work when it needs to be closed modal.Close().

To Reproduce
Steps to reproduce the behavior:

  1. Use Rebus
  2. Send a message to RabbitMQ server
  3. The message is handled by the consumer
  4. Calls an event in the UI, the modal is opened correctly, but is not closed when some code in between ends

Expected behavior
The modal would have to be closed once we call the method .close

Hosting Model (is this issue happening with a certain hosting model?):

  • Blazor Server
  • RabbitMQ
  • Rebus

Thanks in advance for your help.

@HenryDeveloper HenryDeveloper added Bug Something isn't working Triage Issue needs to be triaged labels Mar 1, 2023
@UweReisewitz
Copy link

UweReisewitz commented Sep 5, 2023

This also happens when Show() is called from a Timer Event.

Show() needs to be done from the UI Thread. I have a MAUI Blazor Hybrid App. When I call Show() from the Main Thread (via MainThread.BeginInvokeOnMainThread) then it works a expected. If I call Show() without switching to the Main Thread it behaves as described above.

Thanks in advance for your help.

Addendum: Thinking about it, maybe it's just that Show() and Close() need to be made from the same (not necessarily the UI-) Thread.

@UweReisewitz
Copy link

I have created a workaround in my app that enforces the Show() and Hide() to the UI-Thread by routing it to a Component and call them through InvokeAsync(). This works.
Maybe Show() and Hide() should do the same.

@chrissainty
Copy link
Member

chrissainty commented Sep 6, 2023

Hi @UweReisewitz.

The handler for the event triggered by the Show and Hide methods does use InvokeAsync to execute the StateHasChanged call.

await InvokeAsync(StateHasChanged);

@UweReisewitz
Copy link

Hi, @chrissainty,
the problem seems to arise when Show() and/or Close() are not called on the UI-Thread. In my case Show() was called from a different Thread (Timer Event) and Close() was called from the UI Thread. After I forced both calls into the UI Thread it worked again.
I'm sorry that I am not familiar with the inner workings, therefore I can only speculate here. Would it be possible to move the current contents of Show() and Close() into new private methods and call them via InvokeAsync() from the original Methods?

@chrissainty chrissainty added Needs: More Information The author needs to provide more information on the issue. and removed Triage Issue needs to be triaged labels Feb 20, 2024
@jasperzeinstra
Copy link

jasperzeinstra commented Feb 29, 2024

I also had this issue. I had a modal that I wanted to close based on a timer. But the timer was indeed running on a different thread. First i thought the issue was in the following piece of code. I thought StateHasChanged(); should have been replaced by InvokeAsync(StateHasChanged);.

    public async Task CloseAsync(ModalResult modalResult)
    {
        // Fade out the modal, and after that actually remove it
        if (AnimationType is ModalAnimationType.FadeInOut)
        {
            OverlayAnimationClass += " fade-out";
            StateHasChanged();
            
            await Task.Delay(400); // Needs to be a bit more than the animation time because of delays in the animation being applied between server and client (at least when using blazor server side), I think.
        }
        else if (AnimationType is ModalAnimationType.PopInOut)
        {
            OverlayAnimationClass += " pop-out";
            StateHasChanged();

            await Task.Delay(400);
        }

        await Parent.DismissInstance(Id, modalResult);
    }

Now I've resolved it by doing the CloseAsync itself in a InvokeAsync in the method when my Timer is finished:

InvokeAsync(ModalInstance.CancelAsync());

@chrissainty maybe you can add this trick to the documentation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Needs: More Information The author needs to provide more information on the issue.
Projects
None yet
Development

No branches or pull requests

4 participants