【问题标题】:Wrapping my head around async await把我的头绕在异步等待上
【发布时间】:2017-09-27 00:54:01
【问题描述】:

请原谅明目张胆的新手问题。有一些关于 async 和 await 的东西我没有掌握。

为了使方法异步,它必须等待同样是异步的任务/方法的返回。正确的?但是在某些时候,是否必须有一个不是异步的或不会等待任何东西的任务?

我一直在阅读这两个教程:

https://msdn.microsoft.com/en-us/magazine/hh456401.aspx

https://msdn.microsoft.com/en-us/library/mt674882.aspx

我一直在这里查看很多其他线程。但是还有一点我不明白。我会试着举一个简单的例子。假设我想将值写入数据库中的列:

 public async Task<SimpleObject> ExecuteAsync(int rowID, string value)
 {
    return await WriteToDB(int rowID, string value);
 }

到目前为止一切顺利。但是,这就是我迷路的地方:

 public async Task<SimpleObject> WriteToDB(int rowID, string value)
 {
      var dataRow = context. /// use linq to get a row with rowID
      dataRow.SomeColumn = value
      context.SaveChanges();
      var simpleObject = new SimpleObject();
      simpleObject.success = true;
      return simpleObject;
 }

 public class SimpleObject
 {
    public bool success {get;set;}
 }

VS 非常礼貌地告知我我的方法WriteToDB() 缺少await 并将同步运行。我仍然可以编译,并且不会出现运行时错误。但是,我不知道如何在WriteToDB() 中使用await

【问题讨论】:

  • EF中没有SaveChangesAsync()方法吗?
  • 可能相关文章:“There is no thread
  • 不仅有SaveChangesAsync,还有很多用于数据检索的异步方法(如FirstAsync或ToListAsync),所以第一行就已经有了await。

标签: c# .net asynchronous


【解决方案1】:

您需要使用 .SaveChangesAsync 方法。

 public async Task<SimpleObject> WriteToDB(int rowID, string value)
 {
      var dataRow = context. 
      dataRow.SomeColumn = value
      await context.SaveChangesAsync(); //change this line
      var simpleObject = new SimpleObject();
      simpleObject.success = true;
      return simpleObject;
 }

【讨论】:

    【解决方案2】:

    EntityFramework 支持 async query and save operations 如 SaveChangesAsync 和 ToListAsync,这些异步方法遵循 "Task-based Asynchronous Pattern" 并返回您可以等待的 TaskTask&lt;T&gt;

    您可以重写代码以异步方式执行查询和保存,如下所示:

    public async Task<SimpleObject> WriteToDB(int rowID, string value)
    {
        var dataRow = await context.table.SingleAsync(item =>item.Id = /*some value*/);
        dataRow.SomeColumn = value
        await context.SaveChangesAsync();
        var simpleObject = new SimpleObject();
        simpleObject.success = true;
        return simpleObject;
    }
    

    【讨论】:

      【解决方案3】:

      我会试着举一个简单的例子。

      正如其他人所指出的,简单示例的简单答案是“使用SaveChangesAsync 而不是SaveChanges”。

      要回答“我如何开始使用异步”这个更广泛的问题,最好的方法是:

      1. 识别代码库中的自然异步操作。这些通常是 I/O 操作。在此示例中,将更改保存到数据库。
      2. 将这些 API 更改为使用异步 API,并使用 await。在本例中,将 SaveChanges 更改为 await SaveChangesAsync
      3. 编译器会通知您更改包含方法以使用async,它还会为您提供正确的返回类型以供使用。在此示例中,编译器将指示您将 SimpleObject WriteToDB(..) 更改为 async Task&lt;SimpleObject&gt; WriteToDBAsync(..)

      重复步骤 (2) 和 (3),直到您的应用程序编译完成。在此示例中,步骤 (2) 会将调用 return WriteToDB(int rowID, string value); 更改为 return await WriteToDBAsync(int rowID, string value);,步骤 (3) 会将 SimpleObject Execute(..) 更改为 async Task&lt;SimpleObject&gt; ExecuteAsync(..)

      以这种方式申请async/await要容易得多,从最低级别开始,然后从那里发展。

      但是在某些时候,是否必须有一个不是异步的任务或不会等待任何东西的任务?

      是的。最底层的方法一般由TaskFactory.FromAsyncTaskCompletionSource&lt;T&gt;实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-22
        • 2020-12-13
        • 1970-01-01
        • 2023-03-12
        • 2016-07-07
        • 2016-03-25
        相关资源
        最近更新 更多