Ich habe eine kleine WPF-Anwendung, die in erster Linie nach MVVM-Muster geschrieben wird. Der Punkt des Programms besteht darin, die Zeilen einer Textdatei zu lesen, die Daten daraus zu analysieren, diese Daten in eine Liste von Objekten zu schreiben und dann die Daten in diese Objekte in eine spezifisch formatierte .CSV-Datei zu schreiben.Wie Implementieren von BackgroundWorker in WPF mit MVVM/ICommand-Muster
Obwohl ich die BackgroundWorker-Klasse selbst auf die gleiche Weise implementiert habe, die ich immer mit anderen Anwendungen habe, rufe ich diesmal die RunWorkAsync() -Methode innerhalb der Execute() -Methode meines ICommand auf. Während die endgültige Ausgabe korrekt ist und die Anwendung tatsächlich das gewünschte Ergebnis liefert, stürzt die UI STILL ab, während der BackgroundWorker ausgeführt wird.
Ich habe meine BackgroundWorker-Mitglieder und die gesamte Logik in einer Klasse namens "ReaderWriter" mit einem Konstruktor, der mein ViewModel als Parameter verwendet, eingepackt.
Durch den Aufruf der "StartProcess" -Methode meiner ReaderWriter-Instanz wird der RunWorkerAsync() des BackgroundWorker aufgerufen - hier hatte ich gehofft, dass er einen anderen Thread übernimmt und meinen lang andauernden Prozess zum Lesen der Quelldatei ausführt Analysieren der Daten und Schreiben der neuen Datei; während ReportProgress() regelmäßig aktualisiert wird, um die ProgressBar zu aktualisieren. Hier
ist der Code für meine Readerwriter Klasse:
class ReaderWriter
{
private LogDataViewModel vm { get; set; }
private BackgroundWorker bw { get; set; }
public ReaderWriter(LogDataViewModel viewModel)
{
vm = viewModel;
}
public void StartProcess()
{
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(ReadFromSource);
bw.ProgressChanged += new ProgressChangedEventHandler(UpdateProgress_Read);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Completed_Read);
bw.RunWorkerAsync();
}
private void ReadFromSource(object sender, DoWorkEventArgs e)
{
double records = 0;
string[] lines = File.ReadAllLines(vm.SourcePath);
int lineCount = lines.Length;
double currentLine = 0;
bw.ReportProgress(0, lineCount);
foreach (var line in lines)
{
if (line.Length > 0)
{
string syntax = line.Substring(17, 6);
switch (syntax)
{
case "$WIMDA":
string[] segments = line.Replace(": <- ", ",").Split(',');
vm.LineItems.Add(new LineItem()
{
Time = segments[0],
HgPressure = segments[2],
BarPressure = segments[4],
AirTemp = segments[6],
RelHumidity = segments[10],
TrueWindDir = segments[14],
KnotsWindSpeed = segments[18],
MpsWindSpeed = segments[20]
});
break;
case "$GPGGA":
break;
default:
break;
}
}
currentLine++;
bw.ReportProgress(1, currentLine);
}
using (StreamWriter writer = new StreamWriter(vm.OutputPath))
{
writer.WriteLine($"Time,Pressure(Bar),Pressure(Hg),AirTemp({((vm.ConvertTempSetting) ? "F" : "C")}),RelativeHumidity,TrueWindDirection,WindSpeed(Knots),WindSpeed(M/s)");
foreach (var lineItem in vm.LineItems)
{
writer.WriteLine($"{lineItem.Time},{lineItem.BarPressure},{lineItem.HgPressure},{((vm.ConvertTempSetting) ? Converters.ConvertFromCelcius(Convert.ToDouble(lineItem.AirTemp)).ToString() : lineItem.AirTemp)},{lineItem.RelHumidity},{lineItem.TrueWindDir},{lineItem.KnotsWindSpeed},{lineItem.MpsWindSpeed}");
records++;
}
}
e.Result = records;
}
private void UpdateProgress_Read(object sender, ProgressChangedEventArgs e)
{
vm.IncrementProgress();
switch (Type.GetTypeCode(e.UserState.GetType()))
{
case TypeCode.Double:
vm.IncrementProgress();
break;
case TypeCode.String:
break;
case TypeCode.Int32:
vm.AppendStatus(DateTime.Now, $"{(int)e.UserState} lines parsed from log file");
break;
default:
break;
}
if (vm.IsFirst)
{
vm.ProgressIsVisible = true;
vm.IncrementProgress();
vm.SetMaximum((int)e.UserState);
vm.IsFirst = false;
}
}
private void Completed_Read(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
vm.AppendStatus(DateTime.Now, $"Conversion was cancelled by user");
}
else
{
vm.AppendStatus(DateTime.Now, $"{(double)e.Result} records written to {vm.OutputPath}");
}
vm.LineItems.Clear();
}
}
Und für meine Viewmodel:
public class LogDataViewModel : LogDataModel
{
#region Commands
public BeginProcessCommand BeginCommand { get; set; }
public SelectOutputPathCommand OutputCommand { get; set; }
public SelectSourceCommand SourceCommand { get; set; }
public ResetCommand ResetCommand { get; set; }
#endregion
public bool IsFirst { get; set; }
public LogDataViewModel()
{
BeginCommand = new BeginProcessCommand(this);
OutputCommand = new SelectOutputPathCommand(this);
SourceCommand = new SelectSourceCommand(this);
ResetCommand = new ResetCommand(this);
PrepareViewModel();
}
private void PrepareViewModel()
{
ProgressValue = 0;
ProgressMaximum = 0;
ProgressIsVisible = false;
IsFirst = true;
OutputPath = Properties.Settings.Default.RememberedSavePath;
if (LineItems == null) LineItems = new List<LineItem>();
if (StatusActions == null) StatusActions = new ObservableCollection<StatusAction>();
AppendStatus(DateTime.Now, "Initialized Program");
}
}
Und schließlich ist hier der Befehl:
public class BeginProcessCommand : ICommand
{
LogDataViewModel vm;
public BeginProcessCommand(LogDataViewModel viewModel)
{
vm = viewModel;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
bool result = true;
if (!File.Exists(vm.SourcePath))
result = false;
try
{
if (!Directory.Exists(Path.GetDirectoryName(vm.SourcePath)))
result = false;
}
catch
{
result = false;
}
return result;
}
public void Execute(object parameter)
{
ReaderWriter rw = new ReaderWriter(vm);
rw.StartProcess();
}
}
Jede Hilfe bei Dieser Punkt wird sehr geschätzt, da ich seit einiger Zeit damit zu kämpfen habe und versucht habe, nach Lösungen zu suchen gib keine Hilfe für meine besondere Situation. Dies scheint ein ziemlich einzigartiges Szenario zu sein, aber ich hoffe, dass wir es zum Laufen bringen können.
Vielen Dank!
Es ist, weil Sie die Benutzeroberfläche mit Updates pummeling sind. Versuchen Sie nur alle 100 Zeilen einen Fortschritt zu melden. Wenn Sie eine Menge Zeilen haben und die Schleife ziemlich schnell dreht, erhöhen Sie diese Zahl. – Will
Danke, Will. Ich habe getan, was du vorgeschlagen hast und es hat wie ein Zauber funktioniert! –