WPF:如何在UI线程中进行异步调用 [英] WPF: how to make async call in UI thread

查看:804
本文介绍了WPF:如何在UI线程中进行异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆