在我的wpf(c#)应用程序中,当用户按下按钮时会执行一个很长的过程。按下按钮直到执行完整代码,窗口冻结,用户无法在窗口中执行任何其他任务。如何使按钮单击代码作为后台进程,以便窗口响应用户。我尝试了以下方法,但没有成功。
private void btn_convert_Click(object sender, RoutedEventArgs e)
{
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => {
WorkerMethod();
}));
}
其中WorkerMethod是整个代码的函数。任何建议。
的问候,
桑杰塔
答案 0 :(得分:10)
如果您的目标是.NET 4.5,则可以使用async/await
来激活用户界面:
private async void btn_convert_Click(object sender, RoutedEventArgs e)
{
await WorkerMethod();
}
修改您的WorkerMethod
:
private Task WorkerMethod()
{
return Task.Run(() =>
{
// your long running task here
});
}
答案 1 :(得分:7)
这里的答案的替代方案是BackgroundWorker。 它还有一个好处,就是在完成后返回GUI线程。
private void btn_convert_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += WorkerMethod;
worker.RunWorkerCompleted += WorkerEnded;
worker.RunWorkerAsync();
}
private void WorkerMethod()
{
// New thread, cannot access GUI
}
private void WorkerEnded()
{
// Back on the GUI Thread
// Worker is finished
}
答案 2 :(得分:6)
你在这里实际做的是要求UI线程通过Dispatcher运行繁重的任务。
你应该创建一个新的线程/任务,让它运行你的后台方法:
Thread t = new Thread(() => WorkerMethod());
t.Start();
了解更多信息,请阅读:
答案 3 :(得分:1)
您正在调用UI-Dispatcher
上的方法,这会使UI冻结。使用
private void btn_convert_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(new ThreadStart(WorkerMethod));
//assign STA or MTA, etc....
t.Start();
}
查看here以获取有关“System.Threading.Thread`。
的信息答案 4 :(得分:1)
我想到了另一种令我自豪的方式: 如果多线程只有允许IHM为进度条设置动画,如果用户不应该与确定进程的ihm进行交互,或者只是没有时间开发多线程,并且你不能让你的应用程序冻结而没有反馈:
您可以开发一个启动到另一个STA线程的加载器,该线程创建另一个窗口并在冻结窗口的中间显示该加载器。
这是一篇文章,我已经撰写了一篇文章并实现了这样的解决方案:
http://charly-studio.com/blog/a-loader-for-wpf-long-ui-process/
以下是我使用我的组件的方法:
private void MainWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Long UI process context
using (new LongUIProcessContext("Wait while loading..."))
{
Thread.Sleep(2000);
// Sub long ui process context
using (new LongUIProcessContext("Wait while loading 2..."))
{
Thread.Sleep(2000);
}
// Another sub long ui process context
using (new LongUIProcessContext("Wait while loading 3..."))
{
Thread.Sleep(2000);
}
}
}
这就是我建议的板凳:
以下是我所做的工作台的直接链接,您可以在其中找到组件:
答案 5 :(得分:0)
尝试使用Backgroundworker类。您必须注册DoWork事件并创建一个事件处理程序,您可以在其中放入所有处理代码。使用RunWorkerAsync方法启动worker。还有一种方法可以报告您的工作人员进度“ReportProgress”。 RunWorkerCompleted将在您的工作人员完成代码处理时向您显示。尝试在BackgroundWorker之后在互联网上搜索,你会发现很多如何使用它的例子