Индикатор прогресса при загрузке страницы - PullRequest
1 голос
/ 12 марта 2012

У меня есть окно WPF, загрузка которого занимает около 5 секунд. Я хочу сообщить пользователю удобное сообщение и не уверен, что это лучший способ сделать это. Две вещи, о которых я могу думать: 1. Откройте диалоговое окно с сообщением, которое исчезнет после загрузки главного окна. 2. Используйте панель в главном окне, чтобы показать сообщение и загрузить интерфейс в скрытую панель. После загрузки переключите видимость, чтобы панель прогресса загрузки была скрыта, и сделайте панель пользовательского интерфейса видимой.

Я уже реализовал приложение с вариантом 1, но у меня возникают следующие проблемы: 1. Иногда приложение генерирует исключение Thread.Abort, которое перехватывается обработчиком необработанного исключения приложения. 2. Пользователь может закрыть диалоговое окно прогресса, но главное окно продолжает загружаться в любом случае.

Моя реализация диалогового окна прогресса довольно проста. Он использует обычный диалог с сообщением, а затем я написал вспомогательный класс для управления этим:

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();
    }
}

Мой код вызова:

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

    // Do long running UI update loading here.
}

Кто-нибудь знает, как я могу решить проблемы, которые у меня возникают? Кроме того, лучше перейти к решению 2? Или есть какой-то другой способ сделать это более соответствующим WPF?

ТИА

Ответы [ 2 ]

1 голос
/ 12 марта 2012

Иногда приложение генерирует исключение Thread.Abort, которое перехватывается необработанным обработчиком исключений приложения.

Thread.Abort вызывается в основном потоке пользовательского интерфейса.Это источник исключения.Вероятно, это происходит потому, что существует гонка между вызовом Dispose (через конструкцию using) в потоке пользовательского интерфейса и ProgressWaitDialog, выходящим из своего ShowDialog метода самостоятельно, предположительно, после вызова Close изв другом месте кода.

Пользователь может закрыть диалоговое окно прогресса, но главное окно продолжает загрузку.

Диалоговое окно прогресса может быть закрыто, не затрагивая главное окнопотому что он работает в отдельном потоке.

Я не советую запускать этот ProgressWaitDialog в другом потоке, который, кстати, работает правильно только наполовину, потому что ShowDialog отправляет сообщения.Использование более одного потока пользовательского интерфейса довольно сложно и вызывает много странных проблем, некоторые из которых вы уже наблюдаете.

Вам действительно нужно пересмотреть, как происходит эта длительная операция в потоке пользовательского интерфейса.Если это предполагает загрузку данных из базы данных, выполнение групповых вычислений или иным образом не требует касания каких-либо элементов управления пользовательского интерфейса, то эта часть может быть выполнена в рабочем потоке.Если эта длинная операция выполняет много манипуляций с пользовательским интерфейсом, вам нужно отложить часть этого на более позднее время.Например, если ваше окно заполняет сетку 10 000 записей, измените ее так, чтобы она загружала только 100 одновременно, и реализуйте какую-то стратегию подкачки, чтобы загружать следующий пакет только после того, как пользователь нажмет кнопку или что-то еще.

0 голосов
/ 12 марта 2012

Это чистый и привлекательный способ показать пользователю, что загружается ваша форма.

var splashScreen = 
    new SplashScreen(System.Reflection.Assembly.GetExecutingAssembly(),
    @"Resources\MyAppsLogo.png");
splashScreen.Show(true);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...