WPF:如何在UI线程中进行异步调用 [英] WPF: how to make async call in UI thread
问题描述
我在xaml中有一个按钮,其鼠标单击连接到委托命令.在委托命令中,我正在调用另一个方法,该方法创建位图并将其保存为pdf.此方法需要几秒钟(通常超过10秒),在此期间,应用程序将进入无法访问UI的状态,即无法访问UI.在这段时间内,我想展示一些已经在xaml中定义的动画.但是在调用计时功能之前显示它,然后再隐藏它是行不通的.如果我不使用其他线程,它将在计时功能执行结束时显示.
I have a button in xaml whose mouseclick is connected to a delegate command. In delegate command, I am calling another method which creates bit map and saves it to a pdf. This method takes few seconds(usually more than 10 seconds) during which the app goes to Not responding state where the UI is not accessible. During which time I wanted to show some animation which is already defined in xaml. But showing it just before calling the time-taking-function and hiding it afterwards doesnt work. It shows up at the end of time-taking-function execution if i dont use different thread.
因此,我尝试使用创建其他线程并调用此耗时函数.动画加载正常,但是该函数实际上需要访问UI线程中的某些UI对象.它导致以下异常: 调用线程无法访问该对象,因为另一个线程拥有它."
So, I tried using creating a different thread and calling this time taking function. Animation loads fine But the function actually needs to access some UI objects in UI thread. It results in this exception: "The calling thread cannot access this object because a different thread owns it."
有没有办法实现?即在此函数执行期间显示动画?
Is there a way to achieve it ? i.e., to show the animation during this function execution ?
一些代码段:
private void OnExportPDFCommand()
{
PanelLoading = true; // Flag to show animation
Task.Factory.StartNew(() =>
{
CreatePDF(); //time-taking-function
Application.Current.Dispatcher.Invoke(() => PanelLoading = false);
});
}
请举例说明.我是WPF的新手.谢谢.
Please explain with a small example. I am new to WPF. Thanks.
推荐答案
您可以将OnExportPDFCommand
设置为async
方法,将await
设置为您启动的Task
:
You can make OnExportPDFCommand
an async
method and await
the Task
you start:
private async void OnExportPDFCommand()
{
PanelLoading = true; // Flag to show animation
await Task.Run(() =>
{
CreatePDF(); //time-taking-function
});
PanelLoading = false; // stop animation
}
编译器将其转换为状态机.控制流通过await
关键字返回给调用方(UI). Task
完成后,最终将在下一条语句PanelLoading = false
处恢复执行.
The compiler turns this into a state machine. The control flow is returned to the caller (the UI) at the await
keyword. When the Task
finishes, execution is eventually resumed at the next statement PanelLoading = false
.
这样,对PanelLoading
的调用又是在UI线程中的中,并且不应引发任何异常.
This way, the call to PanelLoading
is in the UI thread again and no exception should be raised.
如果需要对UI进行其他调用(在CreatePDF
内部),则可以使用Application.Current.Dispatcher.Invoke(...)
在UI线程上调用这些调用.
If you need to make other calls to the UI (inside CreatePDF
) you can use Application.Current.Dispatcher.Invoke(...)
to invoke these calls on the UI thread.
作为旁注:您可能想要禁用在OnExportPDFCommand()
开头开始的按钮,并在末尾再次启用它.这样一来,您就可以避免多次启动操作,并避免与动画混淆.
As a side note: you might want to disable the button that starts this at the beginning of OnExportPDFCommand()
and enable it again at the end. This way you can avoid to start the operation multiple times and get confused with your animation.
这篇关于WPF:如何在UI线程中进行异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!