2012-03-12 5 views
1

У меня есть окно 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?

ТИА

+0

'_thread.Abort()' - опасный код! Почему вместо этого вы используете индикатор прогресса расширенного инструментария WPF? –

+1

Вместо того, чтобы создавать новый поток для отображения вашего диалога, вы должны действительно показать свое диалоговое окно в уже существующем потоке пользовательского интерфейса и переместить все, что замедляет ваше окно, в другой (не-пользовательский) поток. –

+0

Спасибо AngelWPF и Мэтт: Оба очень хорошие советы. Я установлю расширенный инструментарий WPF, чтобы использовать элемент управления BusyIndicator, который выглядит как лучший способ сделать это. Я также перевешу длительный процесс в фоновый поток. – millie

ответ

0

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

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

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

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

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

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

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

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

Смежные вопросы