为什么我的异步任务会在 GUI 中冻结 AI 动画?

Why is my asynchronous task freezing AI animations in the GUI?

我的代码看起来很像下面这样:

namespace CloudKey
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
    public Page1()
    {
        InitializeComponent();
    }

    private async void button_Click(object sender, RoutedEventArgs e)
    {
        //Begin Loading animation
        Loading.Visibility = Visibility.Visible;

        //Run Task
        await Task.Run(() => LoginCheck());
    }

    async void LoginCheck()
    {
        await Dispatcher.InvokeAsync(
                () =>
                {
                    InitialSessionState iss = InitialSessionState.CreateDefault();
                    StringBuilder ss = new StringBuilder();
                    ss.AppendLine("some code here")
                    using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
                    {
                        Collection<PSObject> results = null;
                        try
                        {
                            runspace.Open();
                            Pipeline pipeline = runspace.CreatePipeline();
                            pipeline.Commands.AddScript(ss.ToString());
                            results = pipeline.Invoke();

                        }
                        catch (Exception ex)
                        {
                            results.Add(new PSObject((object)ex.Message));
                        }
                        finally
                        {
                            runspace.Close();
                            Loading.Visibility = Visibility.Hidden;
                            if //some stuff
                            {
                                //do some things
                            }
                            else
                            {
                                //do some other things
                            }
                        }
                    }
                });
    }
  }
}

我也试过了

Async void LoginCheck()
{
    await Dispatcher.Invoke (() => {//Stuff});
}

结果相同。我实际上不确定两者之间的区别是什么...

无论哪种方式,任务都能正确运行,但动画会在任务开始后立即停止。 :/ 我应该怎么做才能让加载动画按照我想要的方式工作?

编辑:

我应该补充一点,我试图删除

await Dispatcher.InvokeAsync(
            () =>{});

并保留函数的其余部分,但是,这样做时出现以下错误:

The calling thread cannot access this object because a different thread owns it.

我认为只需要删除

await Dispatcher.InvokeAsync(() => { };

围绕代码。查看 Dispatcher.InvokeAsync 的文档,它说 "Executes the specified delegate asynchronously on the thread the Dispatcher is associated with." (source) 链接到页面的 Dispatcher 与页面的线程关联,因此它在 UI 上执行代码线程,仍然。删除周围的函数调用应该使代码在不同的线程上简单地 运行 因为你已经在不同的线程上调用 Task.Run() 到 运行 它。

编辑:遗漏了加载更改的部分,该部分由 UI 线程拥有。这是一个更好地说明问题的实际代码示例:

async void LoginCheck()
{
    InitialSessionState iss = InitialSessionState.CreateDefault();
    StringBuilder ss = new StringBuilder();
    ss.AppendLine("some code here")
    using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
    {
        Collection<PSObject> results = null;
        try
        {
            runspace.Open();
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript(ss.ToString());
            results = pipeline.Invoke();

        }
        catch (Exception ex)
        {
            results.Add(new PSObject((object)ex.Message));
        }
        finally
        {
            runspace.Close();
            Dispatcher.InvokeAsync(() => {
                Loading.Visibility = Visibility.Hidden;
            });

            if //some stuff
            {
                //do some things
            }
            else
            {
                //do some other things
            }
        }
    }
}

因为 Loading.Visibility 是一个 UI 元素,它属于 UI 线程。因此,围绕 Dispatcher.Invoke() 的调用将更改 UI 线程的值,同时仍在另一个线程上执行 db 调用,如上所述。