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

时间:2016-05-10 23:25:29

标签: c# wpf visual-studio asynchronous dispatcher

我的代码看起来非常像以下内容:

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.

1 个答案:

答案 0 :(得分:1)

我认为所需要的就是删除

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

围绕代码。查看Dispatcher.InvokeAsync的Documentation,它说&#34;在与Dispatcher关联的线程上异步执行指定的委托。&#34; (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调用,如上所述。