2012-03-12 4 views
0

У меня есть модифицированный код, но теперь у меня есть еще одна проблема. Исключение InvalidOperation происходит внутри оператора if при проверке информации пользователя. В нем говорится, что вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток.Отображение управления индикатором занятости внутри пользовательского интерфейса

private void finishConfigButton_Click(object sender, RoutedEventArgs e) 
    { 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.WorkerSupportsCancellation = true; 
     bool validated = false; 

     errorLabel.Visibility = System.Windows.Visibility.Collapsed; 
     validationProfile.IsBusy = true; 
     finishConfigButton.IsEnabled = false; 
     backToLoginHyperlink.IsEnabled = false; 

     worker.DoWork += (o, ea) => 
     { 
      if (newUser.ValidateNewUserInformation(newNameTextBox.Text, newEmailTextBox.Text, newUsernameTextBox.Text, newPasswordPasswordBox.Password, ref errorLabel)) 
      { 
       validated = true; 

       string activeDir = Environment.SystemDirectory.Substring(0, 1) + @":\Users\" + Environment.UserName + @"\My Documents\SSK\Users"; 
       string newPath = System.IO.Path.Combine(activeDir, newUser.Username); 
       Directory.CreateDirectory(newPath); 

       newUser.SaveUserData(newUser); 

       newPath = System.IO.Path.Combine(activeDir, newUser.Username + @"\Settings"); 
       Directory.CreateDirectory(newPath); 

       newUserSettings.SetDefaultValues(); 
       newUserSettings.SaveSettings(newUser, newUserSettings); 
      } 
      else 
       validated = false; 

      if (worker.CancellationPending) 
      { 
       ea.Cancel = true; 
       return; 
      } 
     }; 

     worker.RunWorkerCompleted += (o, ea) => 
     { 
      validationProfile.IsBusy = false; 
      finishConfigButton.IsEnabled = true; 
      backToLoginHyperlink.IsEnabled = true; 
     }; 

     worker.RunWorkerAsync(this); 

     if (validated) 
     { 
      IntelliMonitorWindow intelliMonitor = new IntelliMonitorWindow(newUser, newUserSettings); 
      intelliMonitor.Show(); 
      this.Close(); 
     } 
     else 
      errorLabel.Visibility = System.Windows.Visibility.Visible; 
    } 

ответ

1

Что вы здесь делаете, это все работает на потоке пользовательского интерфейса. Это означает, что во время работы тяжелого кода вы блокируете пользовательский интерфейс от перерисовки, и, следовательно, файл validationProfile не обновляется до конца метода, где значение IsBusy равно false.

Что вам нужно сделать, это обработать тяжелый код в новый поток, который может одновременно обновлять интерфейс.

Взгляните на этом блоге, написанной Брайаном Lagunas, создатель расширенного набора инструментальных средств: http://elegantcode.com/2011/10/07/extended-wpf-toolkitusing-the-busyindicator/

Он объясняет, как использовать BusyIndicator с BackgroundWorker.

0

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

Например:

public void finishConfigButton_Click() 
{ 
    worker = new BackgroundWorker(); 

    worker.DoWork += delegate(object s, DoWorkEventArgs args) 
    { 
     //Do the heavy work here 
    }; 

    worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
    { 
     //Things to do after the execution of heavy work 
     validationProfile.IsBusy = false; 
    }; 

    validationProfile.IsBusy= true; 
    worker.RunWorkerAsync(); 
    } 
} 
1

индикатор занятости в коде XAML не имеет никакого содержания. Помещенный некоторый контроль (ы) в него:

<wpfet:BusyIndicator Name="validationProfile" IsBusy="False" BusyContent="Working...Please wait" DisplayAfter="0" Background="DimGray"> 
    <Grid> 
     ... 
    </Grid> 
</wpfet:BusyIndicator> 

Если вы меняете заняты, эти элементы управления будут отключенным и BusyIndicator появится над ними.

Предположим, вы хотите обернуть целое <Grid Background="LightGray"> с помощью BusyIndicator.

0

Наконец-то я понял. Вы не можете использовать объекты пользовательского интерфейса внутри worker.DoWork block.I немного изменил код, и теперь он работает.

private void finishConfigButton_Click(object sender, RoutedEventArgs e) 
    { 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.WorkerSupportsCancellation = true; 

     errorLabel.Visibility = System.Windows.Visibility.Collapsed; 
     validationProfile.IsBusy = true; 
     finishConfigButton.IsEnabled = false; 
     backToLoginHyperlink.IsEnabled = false; 

     bool validated = false; 
     string newName = newNameTextBox.Text; 
     string newEmail = newEmailTextBox.Text; 
     string newUsername = newUsernameTextBox.Text; 
     string newPassword = newPasswordPasswordBox.Password; 
     string errorMessage = "Unknown error."; 

     worker.DoWork += (o, ea) => 
     { 
      if (newUser.ValidateNewUserInformation(newName, newEmail, newUsername, newPassword, ref errorMessage)) 
      { 
       string activeDir = Environment.SystemDirectory.Substring(0, 1) + @":\Users\" + Environment.UserName + @"\My Documents\SSK\Users"; 
       string newPath = System.IO.Path.Combine(activeDir, newUser.Username); 
       Directory.CreateDirectory(newPath); 

       newUser.SaveUserData(newUser); 

       newPath = System.IO.Path.Combine(activeDir, newUser.Username + @"\Settings"); 
       Directory.CreateDirectory(newPath); 

       newUserSettings.SetDefaultValues(); 
       newUserSettings.SaveSettings(newUser, newUserSettings); 

       validated = true; 
      } 
      else 
       ea.Cancel = true; 
     }; 

     worker.RunWorkerCompleted += (o, ea) => 
     { 
      if (validated) 
      { 
       IntelliMonitorWindow intelliMonitor = new IntelliMonitorWindow(newUser, newUserSettings); 
       intelliMonitor.Show(); 
       this.Close(); 
      } 

      validationProfile.IsBusy = false; 
      finishConfigButton.IsEnabled = true; 
      backToLoginHyperlink.IsEnabled = true; 
      errorLabel.Visibility = System.Windows.Visibility.Visible; 
      errorLabel.Content = errorMessage; 
     }; 

     worker.RunWorkerAsync(); 
    } 
Смежные вопросы