简体   繁体   English

使用任务,但用户界面仍然被阻止

[英]Using Tasks but the UI is still blocked

I have a WPF MVVM c# application. 我有一个WPF MVVM c#应用程序。 In one of my views I have to retrieve data from the database after a button is clicked. 在我的一种视图中,单击按钮后,我必须从数据库中检索数据。 The call to the database is really long and so I want to enable a spinner while the call is being made and disable it when the call is done. 对数据库的调用确实很长,因此我想在进行调用时启用微调器,并在调用完成后将其禁用。

So in the method handling the button click (using Command, not code behind) I set the boolean variable to enable the spinner then create a Task that goes fetches the data and set it to an ObservableCollection<T> like this 因此,在处理按钮单击的方法中(使用Command,而不是后面的代码),我设置了boolean变量以启用微调器,然后创建一个Task ,它将获取数据并将其设置为ObservableCollection<T>如下所示

private void GetDataButtonCommand() {
    this.IsBusy = true;
    var tasks = new List<Task>();

    tasks.Add(Task.Factory.StartNew(() =>
    {
        System.Windows.Application.Current.Dispatcher.BeginInvoke(new System.Action(() =>
        {
            var GotData= DBHelper.GetData();
            _observablecollectionname.Clear();
            foreach (var item in GotData)
            {
                _observablecollectionname.Add(item);
            }
        }));
    }));

    var finalTask = Task.Factory.ContinueWhenAll(tasks.ToArray(), datacomplete =>
    {
        this.IsBusy = false;  
    });
}

On completion of the Task I would like to disable the spinner. 完成Task后,我想禁用微调器。

The problem that I am running into is that I am unable to see the spinner during the call. 我遇到的问题是在通话过程中看不到微调框。 The UI is still being blocked, even thou I am using a Task to execute the database query. 即使您正在使用Task来执行数据库查询,UI仍被阻止。

What am I doing wrong? 我究竟做错了什么?

Your code is running on the UI thead. 您的代码正在UI thead上运行。

You do all your operations in System.Windows.Application.Current.Dispatcher.BeginInvoke(new System.Action(() => { ... })) so it's natural to block the UI. 您可以在System.Windows.Application.Current.Dispatcher.BeginInvoke(new System.Action(() => { ... }))进行所有操作,因此自然会阻塞UI。

You should only call the dispatcher when you really need to do an UI action. 仅在确实需要执行UI操作时才应调用调度程序。

Move var GotData= DBHelper.GetData(); 移动var GotData= DBHelper.GetData(); before the dispatcher. 在调度员之前。

But it'd be better to use the async / await pattern/keywords of C# 5.0 and higher. 但是最好使用C#5.0及更高版本的async / await模式/关键字。

I always use the bellow code when I have a long running query. 当我有长时间运行的查询时,我总是使用下面的代码。

    private async void button1_Click(object sender, EventArgs e)
    {
        var list = await GetDatabaseAsync();
        //do whatever you need with the list.
    }



    private async Task<List<string>>  GetDatabaseAsync()
    {
        var list = Task.Run(() =>
        {
            var _observablecollectionname = new List<string>();
            var GotData = Helper.GetData();
            _observablecollectionname.Clear();
            foreach (var item in GotData)
            {
                _observablecollectionname.Add(item);
            }
            return _observablecollectionname;
        });
        return await list;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM