Await/async doesn't work as expected

2020-05-09 18:46发布

I'm getting started on async/await using. I've written simple application using WPF based on MVVM pattern, but it doesn't work as I expected. The program works as there were no asynchronous functions: after executing execute function it freezes and unfreezes only after loop function ended.

Please tell me what part did I get wrong. I'd appreciate any feedback. :)

Here is my modelview class. It inherits from wpf class, that contains definitions of standard wpf functions like 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条回答
我想做一个坏孩纸
2楼-- · 2020-05-09 18:59

There isn't an asynchronous part in your code. Simply using the async keyword doesn't make it so. Use Task.Run instead if you wish to offload synchronous code to a different thread:

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;
}

If you actually have an asynchronous operation, you can use that instead:

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

Guideline: If your "async" method doesn't have an await inside it, it isn't asynchronous.

查看更多
贪生不怕死
3楼-- · 2020-05-09 19:11

You aren't doing anything async. The async keyword does not mean "creates another thread"; it is quite complex, but basically it allows code to work with continuations when another asynchronous operation completes. Good examples would include asynchronous database access, file access, network access, etc. It can also include asynchronous long-running operations via threads and Task.Run. But: you aren't doing that. There is nothing incomplete to await - the code just runs on the main thread. It only schedules a continuation when there is something incomplete to continue from.

To quote the compiler (talking about the loop method):

Warning This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

查看更多
劳资没心,怎么记你
4楼-- · 2020-05-09 19:23

It looks like the problem is your loop function. Even though you have declared it as async there are no await statements in it and you should get a compiler warning as @Marc Gravell pointed out.

The function spins though large number of loop iterations hogging the UI thread which will cause the blocking, it then returns the final value.

So you loop function is in fact a synchronous function. Assuming you were doing this for test purposes a good way to simulate an async operation is to use Task.Delay. E.g:

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

    return 1;
}
查看更多
登录 后发表回答