C# WPF:如何在UI线程中进行异步调用
我在xaml中有一个按钮,它的鼠标点击连接到一个委托命令。在delegate命令中,我调用另一个方法来创建位图并将其保存为pdf。此方法需要几秒钟(通常超过10秒)的时间,在此期间,应用程序进入不响应状态,用户界面不可访问。在此期间,我想展示一些已经在xaml中定义的动画。但是,在调用耗时函数之前显示它,然后隐藏它是行不通的。如果我不使用不同的线程,它会在函数执行的时间结束时显示 因此,我尝试创建一个不同的线程并调用这个计时函数。动画加载很好,但函数实际上需要访问UI线程中的一些UI对象。它会导致以下异常: “调用线程无法访问此对象,因为其他线程拥有它。” 有没有办法做到这一点?i、 例如,在此函数执行期间显示动画 一些代码片段:C# WPF:如何在UI线程中进行异步调用,c#,wpf,multithreading,xaml,C#,Wpf,Multithreading,Xaml,我在xaml中有一个按钮,它的鼠标点击连接到一个委托命令。在delegate命令中,我调用另一个方法来创建位图并将其保存为pdf。此方法需要几秒钟(通常超过10秒)的时间,在此期间,应用程序进入不响应状态,用户界面不可访问。在此期间,我想展示一些已经在xaml中定义的动画。但是,在调用耗时函数之前显示它,然后隐藏它是行不通的。如果我不使用不同的线程,它会在函数执行的时间结束时显示 因此,我尝试创建一个不同的线程并调用这个计时函数。动画加载很好,但函数实际上需要访问UI线程中的一些UI对象。它会导
private void OnExportPDFCommand()
{
PanelLoading = true; // Flag to show animation
Task.Factory.StartNew(() =>
{
CreatePDF(); //time-taking-function
Application.Current.Dispatcher.Invoke(() => PanelLoading = false);
});
}
请举例说明。我是WPF的新手。谢谢。您可以将
OnExportPDFCommand
设置为async
方法,然后等待您启动的任务
:
private async void OnExportPDFCommand()
{
PanelLoading = true; // Flag to show animation
await Task.Run(() =>
{
CreatePDF(); //time-taking-function
});
PanelLoading = false; // stop animation
}
编译器将其转换为状态机。控制流在wait
关键字处返回给调用者(UI)。当任务
完成时,执行最终会在下一条语句panelload=false
中恢复
这样,对PanelLoading
的调用将再次出现在UI线程中,不应引发任何异常
如果需要对UI进行其他调用(在CreatePDF
中),可以使用Application.Current.Dispatcher.Invoke(…)
在UI线程上调用这些调用
作为旁注:您可能希望禁用在OnExportPDFCommand()
开头启动此操作的按钮,然后在结尾再次启用它。这样可以避免多次启动操作并与动画混淆。您可以将OnExportPDFCommand
设置为async
方法,并等待您启动的任务
:
private async void OnExportPDFCommand()
{
PanelLoading = true; // Flag to show animation
await Task.Run(() =>
{
CreatePDF(); //time-taking-function
});
PanelLoading = false; // stop animation
}
编译器将其转换为状态机。控制流在wait
关键字处返回给调用者(UI)。当任务
完成时,执行最终会在下一条语句panelload=false
中恢复
这样,对PanelLoading
的调用将再次出现在UI线程中,不应引发任何异常
如果需要对UI进行其他调用(在CreatePDF
中),可以使用Application.Current.Dispatcher.Invoke(…)
在UI线程上调用这些调用
作为旁注:您可能希望禁用在OnExportPDFCommand()
开头启动此操作的按钮,然后在结尾再次启用它。通过这种方式,您可以避免多次启动操作并与动画混淆。@vinmm作为旁白。boolpanelloading
模式可能不是一个好主意。如果多次调用OnExportPDFCommand()
,则可能会出现与panelload
标志相关的意外行为。最好将bool PanelLoading
替换为int,您可以使用interlocted.Increment
和interlocted.Decrement
替换为。@Rene Vogt:我已经为您提到的旁注设置了标记。谢谢但我还是有问题。createPDF函数有许多对UI对象的引用(在许多地方都是如此),因为它是一个处理位图和文件的繁重操作。因此,将调用添加到所有许多地方将是困难的。有没有更好的替代方案谢谢你的片段。@vinmm我个人喜欢这种方法,但这也意味着要改变所有这些地方。如果您直接从该方法访问UI,我想不出一个解决方案不需要更改所有这些位置。@vinmm一个更好的Progress
:是的。这就是问题所在。我的函数使用了UI中的许多内容:(.感谢您提供的所有信息。@vinmm作为旁白。bool panelload
模式可能不是一个好主意。如果您调用OnExportPDFCommand()
多次,您可能会出现与面板加载
标志相关的意外行为。最好将bool panelload
替换为int,您可以使用interlocted.Increment
和interlocted.decreation
。@Rene Vogt:我已经为您提到的s旁注。谢谢。但我仍然有问题。createPDF函数有很多对UI对象的引用(实际上在很多地方)因为这是一个处理位图和文件的繁重操作。因此,将调用添加到所有许多位置会很困难。有没有更好的替代方法?&谢谢你的代码片段。@vinmm我个人喜欢这种方法,但这意味着也要更改所有这些位置。如果你直接从该方法访问UI,我想不出一个解决方案不需要更改所有这些位置。@vinmm一个更好的进度链接
:是的。这就是问题所在。我的函数使用了UI中的许多内容。:。感谢您提供的所有信息。