我需要显示某种形式的反馈给用户,而一个小进程(7-10秒)发生在后台。
过去,我在Windows中使用单独的线程和BackgroundWorkers没有问题,但是在WPF中很难做到这一点。
在这方面,我读过许多文章,以及如何使用WPF中的调度程序启动新线程等等。然而,当我试图使用BackgroundWorker显示等待的图像反馈形式时,它只是静止的。
我不认为这很重要,但它使用了FirstFloor (https://github.com/firstfloorsoftware/mui)的mui。
我正在尝试使用内置的ProgressRing特性(它在同一个线程中运行时没有问题,后台也没有运行其他主要任务。
添加BackgroundWorker会导致对象的跨线程访问带来异常,尽管许多博客指出WPF中的BackgroundWorks具有跨线程感知和安全运行的特性。
下面是生成我所需内容的最接近的代码。
private async void MyTaskProcess()
{
await Dispatcher.BeginInvoke(DispatcherPriority.Send, new ThreadStart(() =>
{
try
{
//Update the waiting ring image
ProgressRing.IsActive = true;
}
catch
{
ProgressRing.IsActive = false;
MessageBox.Show("Exception Thrown");
}
}));
await Dispatcher.BeginInvoke(DispatcherPriority.Background, new ThreadStart(() =>
{
try
{
//Run the main MS Excel export function
Export2Excel();
ProgressRing.IsActive = false;
}
catch
{
MessageBox.Show("Exception Thrown");
}
}));
}如有任何反馈,将不胜感激。
发布于 2015-05-15 13:32:39
在现代WPF应用程序中,您这样做的方法是启动一个新的Task,您可以在其中完成这项工作;在幕后,它将在线程池线程上执行工作:
Task.Factory.StartNew(this.DoWork)现在,在DoWork中,当InvokeAsync计数发生变化时,要报告进度,您可以返回到主线程:
void DoWork()
{
foreach(var item in this.WorkItems)
{
// Do something
// Report Progress
++progress
Application.Current.Dispatcher.InvokeAsync(() => this.Progress = progress);
}
}发布于 2015-05-15 20:29:02
添加BackgroundWorker会导致对象的跨线程访问带来异常,尽管许多博客指出WPF中的BackgroundWorks具有跨线程感知和安全运行的特性。
只要您在UI线程上创建和启动BGW,BackgroundWorker就可以很好地处理WPF。(附带说明,BGW对Windows窗体也有相同的限制)。正如其他评论者所指出的,使用BGW进行进度更新的正确方法是使用ReportProgress,而不是使用Dispatcher。
但是,我建议使用更新的Task.Run和IProgress<T>进行进度更新。我有一个博客帖子,它比较/对比旧的BGW进度更新和新的IProgress<T>-based进度更新。
很难说出您的代码应该是什么样子,因为您发布的代码实际上没有在后台线程上运行任何内容。特别是,如果Export2Excel必须在UI线程上运行,而这就是您所做的全部工作,那么使用BGW或Task.Run根本就没有意义,因为任何东西都不能在后台线程上运行。
发布于 2015-05-15 12:50:31
你可以去看我写的下面的链接,仔细阅读,我希望你能彻底解决你的问题:
WPF中的线程
https://stackoverflow.com/questions/30258841
复制相似问题