如何在 c# 中实际编写/结束异步方法

本文关键字:结束 异步方法 | 更新日期: 2023-09-27 18:13:02

我知道我需要在async标记的方法中等待事物以使其异步,但我不知道如何实际结束它造成的漏洞。

static async void Example()
{
    int t = await getIntAsync();
    WriteLine($"computer: {t}");
}

由于getIntAsync被标记为异步,因此我必须在该方法中等待,否则会收到警告。但是哦,不,在我在getIntAsync中等待的方法中,我必须将其标记为aasync,然后除非那里有等待,否则我会收到警告。依此类推,似乎无穷大。我怎样才能让它停止?

我有几个人告诉我把

await Task.Delay(1000);  
在我的代码中

,但我知道答案不能像在所有生产代码中延迟一秒那样臭。

其他几个人说了一个任务方法来结束它,例如

static Task task()
{
  //code
}

但是,除非我标记async否则它会引发同样的警告,让我陷入这种混乱。 我知道

static Task task()
{
  //code
  return Task.FromResult(0);
}

从技术上讲,它可以工作,但同样,这似乎太过代码气味,无法在整个生产中出现。

我只是不明白...

编辑:因为它是被要求。我知道这是一种非常微不足道的方法,但它也只是我用来练习的方法。

    static async Task<int> getIntAsync()
    {
        Console.Write("Enter the number: ");
        int n = int.Parse(Console.ReadLine());
        return n;
    }

如何在 c# 中实际编写/结束异步方法

这里令人困惑的是,你并没有真正做一些异步的事情。 Console.ReadLine()是一种同步方法。简单地在某处键入asyncawait并不能神奇地使其异步。

由于此代码仅用于测试和学习,因此使其异步的一种方法是使用 Task.Run() 将其放在另一个线程上(对于生产代码中的许多情况,我不建议这样做(:

static Task<int> getIntAsync()
{
    Console.Write("Enter the number: ");
    return Task.Run(() => int.Parse(Console.ReadLine());
}

这里不需要async关键字,因为您没有等待某些东西。您只需返回一个Task<int>,该在用户输入值并解析该值时完成。

然后,您的Example()方法的工作方式是这样的:

static async void Example()
{
    int t = await getIntAsync();
    WriteLine($"computer: {t}");
}

命中await时,控制流将返回到调用方,此方法的其余部分(对t的分配和对Console.WriteLine()的调用(被调度为在getIntAsync()返回的Task<int>完成时执行的延续。

需要以下内容(async 关键字是必需的,await 也是必需的,这只是最佳实践(:

  1. 异步关键字
  2. 等待关键字
  3. 您希望在异步进程运行时独立工作的某些进程。
  4. 通常,返回的值来自您的 await 任务(它应该填充结束孔(。

下面是使用 StreamReader 的示例,

async Task<string> GetStringFromReaderAsync()
{
  Streamreader sr = new StreamReader("filename.txt");
     Task<string> getStringTask = sr.ReadLineAsync("filepath");
    //Allow user to continue with some other work.
     DoFileLookup();
  string result = await sr.getStringTask();
  return result.ToString();
}

更多信息:https://msdn.microsoft.com/en-us/library/system.io.streamreader.readlineasync(v=vs.110(.aspx

更多关于 Async 和 Await: https://msdn.microsoft.com/en-us/library/mt674882.aspx

static async Task<int> getIntAsync()
{
    Console.Write("Enter the number: ");
    int n = int.Parse(Console.ReadLine());
    return n;
}

这将同步运行,因为没有 await 语句,也没有对异步方法的等待调用

一般的想法是这样的

   public async Task<int> ExecuteAsync() //Method return type is Task<int>
   {
      // Error: return type is not int. Return type is Task<int>
      return db.SaveChangesAsync(); 
      // OK: returns a task handle that you can await on in you code that called ExecuteAsync()
      // you thread continues processing in your calling function until you try to read the value from this return statement.
      return await db.SaveChangesAsync(); 
      // Ok. Your Thread leaves here and returns when result available.
      // no further Processing done in calling function
      return db.SaveChangesAsync().Result; 
      // Ok. This is not required in this case, 
      // but if you have an async method that has multiple return points, 
      // and one of them does not depend on an async method, you can wrap
      // the output e.g. return await Task.FromResult(0); 
      return await Task.FromResult(db.SaveChangesAsync().Result); 
      return 0; //also ok.
   }

添加到下面的另一个答案。

static async Task<int> GetIntAsync()
{
    Console.Write("Enter the number: ");
    return await Task.Run(() => int.Parse("1"));
}

这种方法使同步运行的内容包装在任务中。但是,您永远不应该这样做(除非您当然知道自己在做什么(,因为这会生成另一个线程。我使用它的一个用例是在网络服务器中卸载,但除此之外,这通常是一个坏主意。因此,虽然您可能一开始的意图是最大限度地利用单个线程,但现在您最终得到了两个线程的工作。