【问题标题】:Await/async doesn't work as expected等待/异步无法按预期工作
【发布时间】:2023-03-03 16:19:01
【问题描述】:

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

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

这是我的模型视图类。它继承自 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;
    }
}

【问题讨论】:

标签: c# wpf asynchronous mvvm async-await


【解决方案1】:

您的代码中没有异步部分。仅仅使用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;
}

准则:如果您的“异步”方法内部没有 await,则它不是异步的。

【讨论】:

    【解决方案2】:

    你没有做任何异步的事情。 async 关键字并不意味着“创建另一个线程”;它相当复杂,但基本上它允许代码在另一个异步操作完成时使用延续。好的示例包括异步数据库访问、文件访问、网络访问等。它还可以包括通过线程和Task.Run 进行的异步长时间运行操作。但是:你没有这样做await 没有什么不完整的——代码只是在主线程上运行。它只安排一个延续当有不完整的东西要继续时

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

    警告此异步方法缺少“等待”运算符,将同步运行。考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。

    【讨论】:

    • 感谢您的回复,这是我不知道的!
    • @RicoW 关键点:await 从不创建线程;如果您等待的事情已经完成,它会继续进行;否则它会为那个“东西”添加一个延续,当 that 完成时,它会从那里运行延续
    【解决方案3】:

    看起来问题出在您的 loop 函数上。即使您已将其声明为 async,其中也没有 await 语句,并且您应该得到编译器警告,正如 @Marc Gravell 指出的那样。

    该函数通过大量循环迭代占用 UI 线程,这将导致阻塞,然后返回最终值。

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

    例如:

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

    【讨论】:

      猜你喜欢
      • 2019-04-19
      • 2019-12-29
      • 2020-03-04
      • 2019-04-07
      • 2022-01-22
      • 2018-12-02
      • 1970-01-01
      • 2017-08-28
      • 2021-07-15
      相关资源
      最近更新 更多