简体   繁体   中英

Await/async doesn't work as expected

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

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.

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.

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 through large number of loop iterations hogging the UI thread which will cause the blocking, it then returns the final value.

So your 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 .

For example:

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

    return 1;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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