Await / async无法按预期工作

时间:2014-09-03 11:44:31

标签: c# wpf asynchronous mvvm async-await

我开始使用async / await。我使用基于MVVM模式的WPF编写了简单的应用程序,但它并没有像我预期的那样工作。该程序的工作原理是没有异步函数:执行执行函数后,只有在循环函数结束后才会冻结和解冻。

请告诉我哪些部分我弄错了。我很感激任何反馈。 :)

这是我的modelview类。它继承自wpf类,它包含标准wpf函数的定义,如OnPropertyChanged。

public class ModelView : wpf
{
    string _state;
    public string state { get { return _state; } set { _state = value; OnPropertyChanged("state"); } }
    public DelegateCommand work { get; set; }

    public ModelView()
    {
        state = "Program started";

        work=new DelegateCommand(_work);
    }

    async void _work(object parameter)
    {
        state = "Working...";

        int j=await loop();

        state = "Done: " + j;
    }

    async Task<int> loop()
    {
        int i;
        for(i=0;i<1000000000;i++);

        return i;
    }
}

3 个答案:

答案 0 :(得分:10)

代码中没有异步部分。仅使用async关键字并不能实现这一目标。如果您希望将同步代码卸载到其他线程,请使用Task.Run

async void _work(object parameter)
{
    status = "Working...";
    int j=await Task.Run(() => loop());
    status = "Done: " + j;
}

int loop()
{
    int i;
    for(i=0;i<1000000000;i++);
    return i;
}

如果您实际上有异步操作,则可以改为使用它:

async void _work(object parameter)
{
    status = "Working...";
    await Task.Delay(1000);
    status = "Done: " + j;
}

指南:如果您的&#34; async&#34;方法里面没有await,它不是异步的。

答案 1 :(得分:5)

你没有做任何异步的事情。 async关键字并不意味着&#34;创建另一个线程&#34 ;;它非常复杂,但基本上它允许代码在另一个异步操作完成时使用continuation 。好的例子包括异步数据库访问,文件访问,网络访问等。它还可以包括通过线程和Task.Run的异步长时间运行操作。但是:你不是那样做的await没有任何不完整的内容 - 代码只是在主线程上运行。它只会在有一些不完整的内容时安排继续

引用编译器(谈论loop方法):

  

警告此异步方法缺少等待&#39;运营商并将同步运行。考虑使用&#39; await&#39;运营商等待非阻塞API调用,或等待Task.Run(...)&#39;在后台线程上进行CPU绑定工作。

答案 2 :(得分:1)

看起来问题是你的loop功能。即使您已将其声明为async,但其中没有await语句,您应该收到编译器警告,因为@Marc Gravell指出。

该函数通过大量循环迭代来旋转,这会占用阻塞的UI线程,然后返回最终值。

所以你的循环函数实际上是一个同步函数。假设您为测试目的而这样做,模拟async操作的一个好方法是使用Task.Delay。例如:

async Task<int> loop()
{
    await Task.Delay(5000);

    return 1;
}