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

ShowMessageAsync freezing when I try to get the result. #1092

Closed
warffen opened this issue Feb 26, 2014 · 10 comments

Comments

@warffen
Copy link

commented Feb 26, 2014

I'm using the ShowMessageAsync wrapped in a service, which has a list of opened Windows. When I try to show the message dialog and get the result, it freezes the application and I have to stop debbuging. I already tried using Wait() method, but it has the same behaviour.

This is my code:

public MessageDialogResult ShowMessage(string message, MessageDialogStyle dialogStyle)
{
    var metroWindow = (_openedViews.First() as MetroWindow);
    metroWindow.MetroDialogOptions.ColorScheme = MetroDialogColorScheme.Accented;

    var messageTask = metroWindow.ShowMessageAsync("MY TITLE", message, dialogStyle, metroWindow.MetroDialogOptions);
    messageTask.Wait();
    return messageTask.Result;
}

I tried calling the ShowMessageAsync on my MetroWindow and it works.
By the way, if I only call the ShowMessageAsync without waiting a result, it works too, but it is not what I want, I need the result to continue my execution. Any idea of what I'm doing wrong here?

[ .net 4.0]

@AzureKitsune AzureKitsune added Question and removed Question labels Feb 26, 2014

@AzureKitsune

This comment has been minimized.

Copy link
Member

commented Feb 26, 2014

@warffen You're not doing anything wrong, that is simply how the dialogs were designed. ShowMessageAsync along with ShowProgress... and ShowInput.... are all what I call "internal dialogs". That is because they are not true dialogs. The are controls that are dropped on top of your MetroWindow's content. Controls need the UI thread to be free to process user input. If you try to wait on the result of an "internal dialog", it causes the UI thread to freeze (because the UI thread is waiting on itself, basically). That is why the functions are asynchronous.

If you need to synchronously wait for a dialog like that, you may want to try the external dialog functions. However, they do not look as nice as the internal dialogs.

@warffen

This comment has been minimized.

Copy link
Author

commented Feb 26, 2014

@Amrykid Ok, I only didn't get the last part you said: "If you need to synchronously wait for a dialog like that, you may want to try the external dialog functions." How could I do that?

I also would like to know how can I activate the overlay option of the MetroWindow? I have some popups (aka MetroWindows in a different size), and I would like to use the overlay, but everytime I try, it throws a NullReferenceException. I'm just creating the new MetroWindow and calling ShowOverlay() (or ShowOverlayAsync()), but it's not working. Should I call something else first?

@warffen warffen closed this Feb 26, 2014

@warffen warffen reopened this Feb 26, 2014

@AzureKitsune

This comment has been minimized.

Copy link
Member

commented Feb 26, 2014

External dialogs can be shown in a similar fashion:

metroWindow.ShowModalDialogExternally(...

It is implemented just like external windows except it is in its own window, thus it has its own (UI Thread/Message Pump).

ShowOverlay function is only 2 lines long. The null exception has to come from our overlayBox variable. Are you calling ShowOverlay before the window is shown? Are you using a custom window style?

@warffen

This comment has been minimized.

Copy link
Author

commented Feb 26, 2014

@Amrykid I only found this ShowModalDialogExternally method only on the DialogManager, I can call it from my MetroWindow. In this case, should I create a dialog for my message?

For the ShowOverlay problem, I'm calling the method before showing the window. This is my code:

public void ShowView<T>(params ParameterOverride[] parameter)
{
    try
    {
        var window = UnityServiceConfigurator.Instance.Container.Resolve<T>(parameter) as MetroWindow;

        if (window != null)
        {
            if (Application.Current.MainWindow != window)
            {
                window.Owner = Application.Current.MainWindow;
                window.ShowOverlay();
            }

            if (_openedViews.Contains(window) == false)
                _openedViews.Add(window);

            window.ShowDialog();
        }
    }
    catch (Exception ex)
    {
        //Do something here
    }
}

When I call window.Show() and then window.ShowOverlay() it works, but the overlay stay inside my window, not behind it covering the whole screen.

@AzureKitsune

This comment has been minimized.

Copy link
Member

commented Feb 26, 2014

The external dialog function hasn't gotten much love. I thought I wrote it as an extension method like ShowMessageAsync. :(

Anyway, you will need to create your own dialog in order to use it like you want. In a later version of MA.M, I'll create a ShowMessageExternally function and probably change the name of ShowModalDialogExternally.

The overlay is also a control inside of the window. You can create a screen-wide overlay by creating a fullscreen window without a titlebar and setting its opacity to 0.7.

@AzureKitsune AzureKitsune self-assigned this Feb 26, 2014

@warffen

This comment has been minimized.

Copy link
Author

commented Feb 26, 2014

@Amrykid I have a lot of changes to do on my project, and I will probably wait your implementation of ShowMessageExternally function (or, as the last option, change the MA.M code... I don't know yet)

For the overlay problem, I have just fixed here. It creates a new layer inside the active window, and I thought it would create behind the active window. So, I started calling Show() instead of ShowDialog() and I'm setting the overlay on its owner window. By the way, WindowStartupLocation="CenterOwner" is not working when the overlay is active.

@warffen

This comment has been minimized.

Copy link
Author

commented Feb 27, 2014

@Amrykid I'm trying to get the value since yesterday, and I finally get the result from the ShowMessageAsync. My service's method, responsible for calling MA.M method must be async and I had to call your method with the await. And the method I call my service must be this way too.

This is my service's method:

public async Task<MessageDialogResult> ShowMessage(string message, MessageDialogStyle dialogStyle)
{
    var metroWindow = (_openedViews.First() as MetroWindow);
    metroWindow.MetroDialogOptions.ColorScheme = MetroDialogColorScheme.Accented;

    return await metroWindow.ShowMessageAsync("MY TITLE", message, dialogStyle, metroWindow.MetroDialogOptions);
}

This is the method I call the service:

private async void Execute()
{
    MessageDialogResult result = await _dialog.ShowMessage("This is just a test", MessageDialogStyle.AffirmativeAndNegative).ConfigureAwait(false);

    if (result == MessageDialogResult.Affirmative)
        _dialog.ShowView<MyView>();
}

It worked as expected, but it will throw an exception with this message: "The calling thread must be STA, because many UI components require this.", due to the ShowView<MyView>() opens a new MetroWindow, but this is only a test, not a real scenario.

Now there is only the WindowStartupLocation="CenterOwner" problem, that is not working how it was supposed to.

@AzureKitsune

This comment has been minimized.

Copy link
Member

commented Feb 27, 2014

Use Dispatcher.InvokeAsync to call ShowView.

The "WindowStartupLocation" thing sounds like a separate issue. Could you open another issue for that so we can close this one?

@flagbug

This comment has been minimized.

Copy link
Member

commented Feb 27, 2014

Use Dispatcher.InvokeAsync to call ShowView.

Actually, the thread should already be the UI thread, so the issue seems to be something else

@warffen

This comment has been minimized.

Copy link
Author

commented Feb 27, 2014

@flagbug @Amrykid I won't use the ShowMessageAsync that way, so it's not a problem for me right now.

Ok, I'm going to open another one. Thank you for the help.

@warffen warffen closed this Feb 27, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.