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

时间:2016-10-14 15:27:35

标签: c# .net async-await

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

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

由于getIntAsync被标记为异步,我必须在该方法中等待,否则我会收到警告。但是我在getIntAsync等待的方法中没有,我必须将其标记为aasync,然后除非在那里有await我得到警告。似乎等等,无穷无尽。我该如何让它停下来?

我有几个人告诉我要把

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;

    }

3 个答案:

答案 0 :(得分:4)

这里令人困惑的是你并没有真正做某事异步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())被安排为<{1}}返回的Task<int>完成后执行的延续。

答案 1 :(得分:0)

需要以下内容(async关键字是必需的,等待,它只是最佳做法):

  1. Async关键字
  2. Await关键字
  3. 在异步流程运行时,您希望独立工作的某些流程。
  4. 通常,您返回的值来自您的等待任务(应该填入最后一洞)。
  5. 以下是使用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

答案 2 :(得分:0)

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

这种方法使得同步运行的东西被包装在任务中。但是你永远不应该这样做(除非你知道你在做什么),因为这会产生另一个线程。我使用过它的一个用例是在web服务器上卸载,但通常情况下这是一个坏主意。因此,虽然您可能已经开始意图最大限度地利用单个线程,但现在您已经完成了两个线程工作。