开发者

MessageBox.Show early in App startup causes app to terminate

As part of my App's startup procedure, it checks data integrity, and if it finds a problem it pops up a message to the user telling them that it might take a while to repair things.

I'm showing the message using MessageBox.Show. Because the data check is done from a worker thread, I'm switching over to the UI thread to make that call, and then setting a ManualResetEvent to tell the worker thread when the user has acknowledged the message.

I kick off the data check/load very early in the app's lifecycle from the constructor in the main Application class, by spinning off a worker thread (using the ThreadPool).

When I run with the debugger, and the message is displayed, the app just waits for input. When I run without the debugger, the app terminates after displaying the dialog for 10 seconds.

That 10 seconds is a big clue - it tells me that the OS thinks the app took too long to initialize (the OS kills apps that take too long to start up).

I think that my MessageBox.Show is blocking the UI thread before the App.RootFrameNavigating has a chance to be invoked.

My questions:

  • Does my di开发者_运维问答agnosis sound right?
  • I'd prefer to kick off my data load early, because it is almost entirely IO, except for this Message Box, and the sooner I can get my Model loaded, the better, but do you normally delay your data load until later in the app lifecycle?
  • Any other ideas/suggestions? I can't guarantee which page will be the start page, because the app could be resuming to any page. I'm also thinking of having the MessageBox.Show delay itself until the app has initialized, perhaps polling away for a flag set by App.RootFrameNavigating - does that make sense?


I think your problem is a result of kicking off the worker thread in the Application constructor. You should use the appropriate life-cycle event, in this case: PhoneApplicationService.Activated Event


So, the solution I've come up with is to still kick off the data load in a worker-thread from the Application's constructor, but in my PhoneService's class ShowDialog method that I invoke to invoke MessageBox.Show, I check to see if the initial navigation has occurred:

private readonly ManualResetEvent _appInitialized = new ManualResetEvent(false);

public void AppInitialized()
{
    _appInitialized.Set();
}


public void ShowDialog(string caption, string text, Action<MessageBoxResult> callback, MessageBoxButton button = MessageBoxButton.OKCancel)
{
    _appInitialized.WaitOne();
    DispatcherHelper.CheckBeginInvokeOnUI(() =>
    {
        var result = MessageBox.Show(text, caption, button);

        if (callback != null)
        {
            callback(result);
        }
    });
}

Then in my Application class:

private bool _firstNavigate = true;
private void RootFrameNavigating(object sender, NavigatingCancelEventArgs e)
{
    if (_firstNavigate)
    {
        _firstNavigate = false;
        var navigationService = (NavigationService) sender;
        navigationService.Navigated += NavigationServiceNavigated;
    }
         ....


private void NavigationServiceNavigated(object sender, NavigationEventArgs e)
{
    var navigationService = (NavigationService)sender;
    navigationService.Navigated -= NavigationServiceNavigated;
    PhoneServices.Current.AppInitialized();
}

Anyone see any issues with this approach? Anyone come up with a better way?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜