执行按钮单击时使 wpf UI 响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15409501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Make wpf UI responsive when button click is performed
提问by Sangeetha
In my wpf (c#) application , a long process is performed when a button is pressed by the user. When button is pressed until the complete code executed the window freezes and user cannot perform any other task in the window. How can I make the button click code as a background process, so that the window become responsive to the user. I have tried the following method, but was unsuccessful.
在我的 wpf (c#) 应用程序中,当用户按下按钮时会执行一个很长的过程。当按下按钮直到执行完完整代码时,窗口会冻结并且用户无法在窗口中执行任何其他任务。如何将按钮单击代码作为后台进程,以便窗口对用户做出响应。我尝试了以下方法,但没有成功。
private void btn_convert_Click(object sender, RoutedEventArgs e)
{
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => {
WorkerMethod();
}));
}
Where WorkerMethod is the function with the entire code. Any suggessions.
其中 WorkerMethod 是整个代码的函数。任何建议。
Regards,
Sangeetha
问候,
桑吉塔
回答by Oliver
If you are targeting .NET 4.5, you can use async/awaitto make your UI responsive:
如果您的目标是 .NET 4.5,您可以使用async/await来使您的 UI 具有响应性:
private async void btn_convert_Click(object sender, RoutedEventArgs e)
{
await WorkerMethod();
}
Modify your WorkerMethod:
修改你的WorkerMethod:
private Task WorkerMethod()
{
return Task.Run(() =>
{
// your long running task here
});
}
回答by AkselK
An alternative to the answers here is a BackgroundWorker. It has the added benefit of returning you to the GUI thread after it's done.
此处答案的替代方法是 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
}
回答by makc
What you have actually done here is asking the UI thread to run your heavy task through the Dispatcher.
您实际上在这里所做的是要求 UI 线程通过 Dispatcher 运行您的繁重任务。
You should create a new thread/Task and let it run your background Method:
您应该创建一个新线程/任务并让它运行您的后台方法:
Thread t = new Thread(() => WorkerMethod());
t.Start();
for further information read this:
欲了解更多信息,请阅读:
WPF BackgroundWorker vs. Dispatcher
WPF BackgroundWorker 与 Dispatcher
回答by bash.d
You are calling the method on the UI-Dispatcher, this will make the UI freeze. Create a new thread in your click-event using
您正在调用 上的方法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();
}
Look herefor information on "System.Threading.Thread`.
看看这里关于“System.Threading.Thread`信息。
回答by Charles HETIER
I have imagined another way I am quite proud of: In case the multithread have benefit only to allow IHM to animate a progress bar, if the user is not supposed to interact with the ihm suring the process or simply if there is no time to developp multithreading and you cannot allow your application to freeze without a feedback:
我想象了另一种让我感到非常自豪的方式:如果多线程的好处只是允许 IHM 为进度条设置动画,如果用户不应该与 ihm 进行交互以确保进程或只是没有时间开发多线程,你不能让你的应用程序在没有反馈的情况下冻结:
you could develop a loader launched into another STA thread that created another window and displays this loader in the middle of the frozen window.
您可以开发一个加载器,该加载器启动到另一个 STA 线程,该线程创建另一个窗口并在冻结窗口的中间显示此加载器。
Here is a post from which I have made an article and an implementation of such a solution:
这是我撰写的文章和此类解决方案的实现的帖子:
http://charly-studio.com/blog/a-loader-for-wpf-long-ui-process/
http://charly-studio.com/blog/a-loader-for-wpf-long-ui-process/
Here is how I use my component:
这是我如何使用我的组件:
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);
}
}
}
And here is what the bench I propose looks like:

这是我建议的长凳的样子:

And here is the direct link of the bench I made in which you can find the components:
这是我制作的工作台的直接链接,您可以在其中找到组件:
回答by Olimpiu Datcu
Try to use the Backgroundworker class. You have to register to the DoWork event and create an event handler where you put all your processing code in. You start the worker with the RunWorkerAsync method. There is also a method that can report your workers progress "ReportProgress". The RunWorkerCompleted will show you when your worker is done processing your code. Try to search on the internet after BackgroundWorker and you will find plenty of examples how to use it
尝试使用 Backgroundworker 类。您必须注册到 DoWork 事件并创建一个事件处理程序,将所有处理代码放入其中。您使用 RunWorkerAsync 方法启动工作程序。还有一种方法可以报告您的工人进度“ReportProgress”。RunWorkerCompleted 将显示您的工作人员何时完成处理您的代码。尝试在BackgroundWorker之后在网上搜索,你会发现很多如何使用它的例子

