我需要向用户显示某种形式的反馈,而在后台进行一个小程序(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");
}
}));
}
感谢任何反馈。
答案 0 :(得分:1)
在现代WPF应用程序中执行此操作的方法是启动一个新的Task
,您可以在其中执行此操作;这将在线程池线程上执行工作:
Task.Factory.StartNew(this.DoWork)
现在在DoWork
中,当porgress计数发生变化时,您将InvokeAsync
的进度报告回主线程:
void DoWork()
{
foreach(var item in this.WorkItems)
{
// Do something
// Report Progress
++progress
Application.Current.Dispatcher.InvokeAsync(() => this.Progress = progress);
}
}
答案 1 :(得分:1)
只需在UI线程上创建并启动BGW,添加BackgroundWorker会因对象的跨线程访问而带来异常,即使许多博客都指出WPF中的BackgroundWorks具有跨线程感知功能且可以安全运行。
BackgroundWorker
可以正常使用WPF,。 (作为旁注,BGW对Windows Forms具有相同的限制)。正如其他评论者所指出的那样,使用BGW进行进度更新的正确方法是使用ReportProgress
,而不是Dispatcher
。
但是,我建议您使用较新的Task.Run
和IProgress<T>
进行更新。我有blog post比较/对比旧的BGW进度更新与基于IProgress<T>
的新进度更新。
很难说出您的代码应该是什么样子,因为您发布的代码在后台线程上实际上并没有运行任何内容。特别是,如果必须在UI线程上运行Export2Excel
,并且您的所有工作都在进行,那么使用BGW或Task.Run
毫无意义,因为无论如何也无法在后台线程上运行。
答案 2 :(得分:0)
你去,到我写的下面的链接,仔细阅读。我希望你能明确地解决你的问题: