【问题标题】:Do I need to mark all methods in the flow with async and await我是否需要用 async 和 await 标记流程中的所有方法
【发布时间】:2018-07-16 17:30:16
【问题描述】:

我有一个调用多个私有方法的公共方法。我必须用 async 和 await 标记流程中的所有方法还是只标记耗时工作的方法?

【问题讨论】:

  • asyncawait 几乎可以肯定不会像您认为的那样做。 async“just”将您可以在方法中编写的内容从“不带await 的C#”更改为“带await 的C#”。 await 是一种在不占用线程的情况下暂停执行的方法。两者都与耗时工作的代码无关(假设该代码受 CPU 限制)
  • 开始阅读here
  • @Damien_The_Unbeliever 大量耗时的工作不受 CPU 限制。像大多数 IO 工作一样。如果它受 CPU 限制,则确实需要多线程。但这种情况相当罕见。根据我的口味,人们倾向于过度使用多线程,即使使用 async+await 进行多任务处理也可以。
  • 我正在从数据库中读取批量数据,我希望此时暂停该过程。要访问数据库,我在该方法中有多个私有方法。我是否需要在该过程中用asyncawait 标记所有方法,还是只标记实际调用数据库的方法。
  • DB Access 听起来就像是在没有多线程的情况下通常可以完成的那种 Multitaskign 工作。但是,根据您在客户端上实际进行处理的方式,可能会有一些 CPU 工作。因此,在这种情况下,适当的多线程可能会更好。如果您不向我们展示您的代码,就无法判断。

标签: c# async-await


【解决方案1】:

不,您不必将所有过程标记为异步,只需将那些调用其他异步函数的过程标记。您可能在调用 .NET 函数时已经这样做了

async Task DoIt(...)
{
     // call async function, wait until finished
     string txt = await ReadMyTextFile();

     // call non-async function
     string reversed = txt.Reverse();

     // call async function, wait until finished
     await WriteMyTextFile(reversed);
} 

如果你调用一个异步函数,你可以确信在这个函数的某个地方有一个等待。事实上,如果您忘记在过程中的某个地方等待,您的编译器会警告您。

如果一个正在执行过程的线程遇到了等待,该线程不会一直等待,直到等待的任务完成,而是向上调用堆栈查看过程的调用者是否没有等待,并继续处理该过程直到遇到等待。再次上调用栈,继续处理直到等待等。

Task<int> ReadNumber(FileStream in
{
    // start fetching data from a database, don't await yet
    Task<int> taskFetchCustomerCount = FetchCustomerCountAsync();

    // once the await is met in FetchCustomerCountAsync, the thread will start doing this
    // also don't need the result yet. Don't await
    Task<MonthlyReport> taskReadReport = ReadMonthlyReportAsync();

    // once the await is met in ReadMonthlyReportAsync the thread will continue doing this
    // this is a non-async function
    string reportPeriod = GetReportPeriod();

    // by now, we need the result from the database. Start waiting for it
    int customerCount = await taskFetchCustomerCount;

    // if the database is not finished yet, the thread goes up the call stack to see 
    // if the caller can continue

    // after a while the database has fetched the result, we can continue
    string customerCountLine = 
        $"At the end of {reportPeriod} the company had {customerCount} customers.";

    // now we need the result from the Report reading:
    MonthlyReport report = await taskReadReport;

    // call a non-async function
    report.SetCustomerCountLine(customerCountLine);

    // save the report. Nothing to do anymore, so await until saving completed
    await report.SaveAsync();
}

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多