【问题标题】:How to execute some code when a block exits due to "await"?当一个块由于“等待”而退出时如何执行一些代码?
【发布时间】:2023-01-11 01:27:15
【问题描述】:

tldr:当“等待”导致方法调用返回时,有没有办法执行一些代码?

假设我使用一个对象记录 C# 方法的进入和退出,该对象的 Dispose() 方法记录方法的退出。例如

void DoWhatever() 
{
    using (LogMethodCall("DoWhatever")
    {
        // do whatever
    } 
}

也就是说,方法 LogMethodCall() 记录“DoWhatever entered”,然后返回类型为 CallEnder 的对象,其 Dispose() 方法记录“DoWhatever exiting”。在使用 await 之前,它工作正常。例如...

async Task DoWhatever()
{
    using (LogMethodCall("DoWhatever")
    {
        // do first part.
        await Something();
        // do second part.
    }
}

上面的代码在遇到等待时向调用方返回一个任务,其余代码(包括对 CallEnder.Dispose() 的调用)在该任务中运行。我的问题是我想在 await 触发实际返回时记录“DoWhatever exiting”,而不是在最终调用 CallEnder.Dispose() 时。

有没有办法做到这一点?当 await 导致 DoWhatever() 返回时,是否会引发类似事件的事件?也许与 ExecutionContext 或 CallContext 或 TaskScheduler 有关?

请注意,我需要保留上面代码中描述的“using (some_object)”模式。该模式可以很好地记录块的进入和退出。我可以更改 some_object 的实现以检测控制何时从 DoWhatever() 返回到其调用者,但我不想更改 DoWhatever() 的实现。虽然我可以,如果没有其他办法。

【问题讨论】:

  • 我认为您对 await 的工作原理有一些错误的假设。即来自这个声明 - when an "await" causes a method call to return
  • @Jonesopolis 但这实际上是await 正在建模的:指令指针在其间来回跳转的协程,在每次跳转时进入和退出每个协程。所以我认为措辞并没有错。 await 使用生成的状态机实现的事实是一个实现细节。
  • @Jonesopolis 我很确定 await 实际上会将控制权返回给调用者,除非等待对象已经完成。

标签: c# async-await


【解决方案1】:

如果您想在 Something 完成任何同步操作并返回任务时进行记录,这很简单:

var task = Something(); 
/* log as you like */ 
await task;

【讨论】:

  • 我想我不清楚我希望日志记录由“using”子句中指定的对象完成。在 async/await 出现并且大量代码已经在使用它之前,该模式一直运行良好。
  • @Kluas 你的建议的另一个问题是 await 可能会也可能不会将控制权返回给调用者。这取决于可等待的(任务)是否已完成。最重要的是,我想在控制权返回(或正在返回)调用者时进行记录。它还需要由 DoWhatever() 启动的同一线程完成。
猜你喜欢
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2018-05-20
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多