【发布时间】:2013-01-08 05:44:16
【问题描述】:
我正在尝试在后台线程中加载文件,同时在 UI 中显示进度条。 BinaryFormatter.Deserialize 函数以及对ProgressBar 的更新似乎需要在 STA 线程上运行。我正在使用 TPL 库将 TaskScheduler.FromCurrentSynchronizationContext() 传递给加载任务,但这似乎将progressbar 更新和文件加载到 same 线程上,以便它们连续发生的并行。
我尝试将TaskScheduler.Default 传递给LoadModelTask,但这会在BinaryFormatter.Deserialize 调用中产生STA 错误。
是否有另一种方法可以在后台加载 WPF 对象而不需要我冻结 UI 线程?
我的代码:
private void openFile()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.DefaultExt = FILE_EXTENSION;
dialog.Filter = "MFlow Documents|*.mpex;*.mpxc;*.mpoc";
Nullable<bool> result = dialog.ShowDialog();
if (result == true)
{
string filename = dialog.FileName;
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
CancellationTokenSource source=new CancellationTokenSource();
CancellationToken token = source.Token;
feedbackWindow = new FeedbackWindow();
feedbackWindow.ProgressBar.IsIndeterminate = true;
feedbackWindow.ProgressLabel.Content = "Opening " + filename;
feedbackWindow.Show();
Task<Model> loadModelTask=
Task.Factory.StartNew<Model>(() => LoadModel(filename),
token, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
loadModelTask.ContinueWith(task => AfterLoadModel(task), scheduler);
}
}
private static Model LoadModel(string filename)
{
Model returnModel;
string extension = filename.Split('.')[filename.Split('.').Length - 1];
Stream stream = File.Open(filename, FileMode.Open);
using (var gZipStream = new GZipStream(stream, CompressionMode.Decompress))
{
BinaryFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
var test = formatter.Deserialize(gZipStream);
returnModel = (Model)formatter.Deserialize(gZipStream);
gZipStream.Close();
stream.Close();
}
}
return returnModel;
}
private void AfterLoadModel(Task<Model> task)
{
try
{
task.Wait();
switch (task.Status)
{
case TaskStatus.RanToCompletion:
ModelResult = task.Result;
feedbackWindow.Close();
break;
default:
break;
}
}
catch (AggregateException ex)
{
// For demonstration purposes, show the OCE message.
foreach (Exception v in ex.InnerExceptions)
{
Debug.WriteLine("msg: " + v.Message);
}
}
}
【问题讨论】:
标签: wpf serialization task-parallel-library background-process