Ich habe eine Stephen Cleary's article gelesen, dass es erforderlich ist, explizit von TaskScheduler.Current
bis TaskScheduler.Default
zu setzen.Task.Factory.StartNew mit TaskScheduler.Default friert UI ein. Net 4.0
Wenn mein Programm gestartet wird, beginnt das Laden von Daten. Es dauert ungefähr 5 Sekunden. Wenn ich beim Laden der Daten auf die Schaltfläche Hinzufügen klicke, wird das neue Fenster erst geöffnet, wenn Task
der Vorgang ReadData()
nicht abgeschlossen ist.
Ansichtsmodell:
public class MainWindowVM:ViewModelBase
{
public MainWindowVM()
{
AddPersonCommand = new RelayCommand<object>(AddPerson);
ReadData();
}
private void ReadData()
{
PersonData = new ObservableCollection<PersonDepBureau>();
IList<PersonDepBureau> persons;
Task.Factory.StartNew(() =>
{
using (PersonDBEntities db = new PersonDBEntities())
{
persons = (from pers in db.Person
join bu in db.Bureau on pers.Fk_IdBureau equals bu.IdBureau
join dep in db.Departament on pers.Fk_IdDep equals dep.IdDep
select new PersonDepBureau
{
IdPerson = pers.IdPerson,
PersonName = pers.Name,
Surname = pers.Surname,
).ToList();
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
foreach (var person in persons)
{
PersonData.Add(person);
}
}));
}
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
}
//Opening new Window AddPersonWindow.xaml
private void AddPerson(object obj)
{
AddPersonWindow addPersonWindow = new AddPersonWindow();
addPersonWindow.DataContext new AddPersonVM();
addPersonWindow.ShowDialog();
}
}
Ausblick:
<extToolkit:BusyIndicator IsBusy="{Binding IsBusy}" Foreground="Black">
<DataGrid ItemsSource="{Binding PersonData}" SelectedItem="{Binding SelectedPerson}"
IsSynchronizedWithCurrentItem="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding PersonName}"/>
<DataGridTextColumn Header="Surname" Binding="{Binding Surname}" />
</DataGrid.Columns>
</DataGrid>
</extToolkit:BusyIndicator>
<Grid Grid.Row="1">
<Button Command="{Binding AddPersonCommand}" Margin="5" Grid.Column="1">Add</Button>
</Grid>
nicht async/await
syntaktischen Zucker verwenden können, wie meine Anwendung kann in Windows XP verwendet werden (ich kann nicht Benutzer fragen .NET 4.5
zu installieren). Danke im Voraus.
Es ist wirklich komisches Verhalten. Alle Informationen, die ich gelesen habe, verwenden Task
wie ich. Aber mein Beispiel funktioniert nicht richtig (neues Fenster wird beim Laden der Daten nicht geöffnet), um das Fehlerverhalten I've made a test application and it can be downloaded here. anzuzeigen. Weil ich viele Kommentare gehört habe, um TaslScheduler.Default
zu verwenden.
Bitte schließen Sie meinen Thread nicht, da es für mich wirklich wichtig ist, den Grund zu verstehen, warum meine Benutzeroberfläche nicht reagiert.
Stephen Cleary Artikel ist perfekt. Vielen Dank für Ihre Geduld an Peter Bons. Die Konstruktion Task.Factory.StartNew(() =>}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
ist perfekt funktioniert, der Grund für das Einfrieren der Benutzeroberfläche ist eine andere Operation auf UI-Thread ausgeführt.
Wenn Sie 'Dispatcher. (Begin) Invoke()' aufrufen, führen Sie den Lambda-Ausdruck im UI-Thread aus. Entfernen Sie den Anruf und rufen Sie ihn nur auf, wenn Sie die Steuerelemente/Elemente der Benutzeroberfläche aktualisieren müssen. –
@VisualVincent Wenn ich Dispatcher lösche, friert es die Benutzeroberfläche immer noch ein. – StepUp
Und wenn Sie 'TaskCreationOptions.AttachedToParent' in' TaskCreationOptions.None' ändern? –