简体   繁体   English

页面加载时的进度指示器

[英]Progress indicator while page loads

I've got a WPF window that takes about 5 seconds to load. 我有一个WPF窗口,大约需要5秒钟才能加载。 I want to inform the user with a user friendly message and wasn't sure the best way to do this. 我想通过用户友好的消息通知用户,并且不确定执行此操作的最佳方法。 The two things I can think of: 1. Throw up a dialog that shows the message and then it disappears once the main window has loaded. 我能想到的两件事:1.弹出一个对话框,显示该消息,然后在主窗口加载后消失。 2. Use a panel on the main window to show the message and load the UI into a hidden panel. 2.使用主窗口上的面板显示消息并将UI加载到隐藏面板中。 When it has loaded, switch the visibility so the load progress panel is hidden and make the UI panel visible. 加载完毕后,请切换可见性,以便隐藏加载进度面板并使UI面板可见。

I've already implemented the application with option 1 but I'm running into the following issues: 1. Occasionally, the application will throw a Thread.Abort exception which gets caught by the application's unhandled exception handler. 我已经用选项1实现了应用程序,但是遇到了以下问题:1.有时,应用程序将引发Thread.Abort异常,该异常会被应用程序的未处理异常处理程序捕获。 2. The user can close the progress dialog but the main window carries on loading anyway. 2.用户可以关闭进度对话框,但主窗口仍会继续加载。

My implementation of the progress dialog is fairly simple. 我对进度对话框的实现非常简单。 It's using just a normal dialog with a message and then I've written a helper class to manage this: 它只使用带有消息的普通对话框,然后编写了一个帮助器类来管理此消息:

public class ProgressWaitDialogHelper : IDisposable
{
    private Thread _thread = null;
    private ProgressWaitDialog _waitDialog;

    public void ShowDialog()
    {
        ThreadStart threadStart = new ThreadStart(ShowDialogAsync);
        _thread = new Thread(threadStart);
        _thread.SetApartmentState(ApartmentState.STA);
        _thread.Start();
    }

    public void Dispose()
    {
        if ((_thread != null) &&
            (_thread.IsAlive))
        {
            _thread.Abort();
            _thread = null;
        }
    }

    private void ShowDialogAsync()
    {
        _waitDialog = new ProgressWaitDialog();
        _waitDialog.ShowDialog();
    }
}

My calling code then does: 我的调用代码然后执行:

using (ProgressWaitDialogHelper waitDialog = new ProgressWaitDialogHelper())
{
    waitDialog.ShowDialog();

    // Do long running UI update loading here.
}

Does anyone know how I can fix the problems I'm seeing? 有谁知道我该如何解决所遇到的问题? Also, is it better to move over to solution 2? 另外,转到解决方案2更好吗? Or, is there some other way of doing this that is more in line with WPF? 或者,还有其他更符合WPF的方法吗?

TIA TIA

Occasionally, the application will throw a Thread.Abort exception which gets caught by the application's unhandled exception handler. 有时,应用程序将引发Thread.Abort异常,该异常会被应用程序未处理的异常处理程序捕获。

Thread.Abort is being called on the main UI thread. 在主UI线程上调用Thread.Abort That is the source of the exception. 那是例外的根源。 It is probably happening because there is a race between calling Dispose (via the using construct) in the UI thread and the ProgressWaitDialog exiting out of its ShowDialog method on its own presumably after Close was called from elsewhere in the code. 发生这种情况的原因可能是在UI线程中调用Dispose (通过using构造)与ProgressWaitDialog自行退出其ShowDialog方法之间的竞争,大概是在代码的其他位置调用Close之后。

The user can close the progress dialog but the main window carries on loading anyway. 用户可以关闭进度对话框,但主窗口仍会继续加载。

The progress dialog can be closed without affecting the main window because it is running on separate thread. 可以关闭进度对话框,而不会影响主窗口,因为它在单独的线程上运行。

I advise against running that ProgressWaitDialog on another thread which, by the way, is only working half-way correctly because ShowDialog pumps messages. 我建议不要在另一个线程上运行该ProgressWaitDialog ,因为ShowDialog泵送消息,所以该线程只能在一半时间正常工作。 Using more than one UI thread is tricky and causes a lot of weird problems some of which you are already observing. 使用多个UI线程很棘手,并且会引起很多奇怪的问题,您已经在其中发现了一些问题。

You really need to reconsider how that long operation on the UI thread is taking place. 您确实需要重新考虑对UI线程进行的长时间操作。 If it involves loading data from database, doing a bunch calculation, or otherwise does not need to touch any UI controls then that part can be executed in a worker thread. 如果涉及从数据库中加载数据,进行堆计算或不需要触摸任何UI控件,则可以在辅助线程中执行该部分。 If this long operation is doing a lot of UI manipulation then you need to defer some of that to a later time. 如果此较长的操作要进行大量的UI操作,则需要将其中的某些操作推迟到以后。 For example, if your window is populating a grid with 10,000 records then change it so that it loads only 100 at a time and implement some kind of paging strategy to load the next batch only after a user clicks a button or whatever. 例如,如果您的窗口正在填充10,000条记录的网格,则对其进行更改,以使其一次仅加载100条记录,并实施某种分页策略以仅在用户单击按钮或其他操作后才加载下一批。

This is clean and attractive way of showing a user your form is loading. 这是一种向用户显示您正在加载表单的干净且有吸引力的方法。

var splashScreen = 
    new SplashScreen(System.Reflection.Assembly.GetExecutingAssembly(),
    @"Resources\MyAppsLogo.png");
splashScreen.Show(true);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM