假设(完全是假设性的;))我有一大堆的 async
代码。
10s的类;100s的异步方法,其中有10s是 其实 做异步工作(例如,在我们 WriteToDbAsync(data)
或者我们 ReadFileFromInternetAsync(uri)
或当 WhenAll(parallelTasks)
.
我想对它进行一系列的诊断调试。我想对它进行灌注剖析,并手动地检查它,看看什么是什么。
我所有的工具都是围绕同步的C#代码设计的。它们将 某种 搭配 async
但它的效果肯定要差很多,而且调试起来也很困难,即使我尝试直接管理一下线程。
如果我只对一小部分代码感兴趣,那么暂时解除async
的那部分代码。同步读写,只需在我的每一个 "并行 "的Task.Wait() Task
的顺序。但如果我想在大量的代码中摸索,那是不可行的。
有没有办法让C#运行一些"async
"这样的代码给我?
即某种 (() => MyAsyncMethod()).RunAsThoughAsyncDidntExist()
它知道,任何时候它与外界进行真正的异步通信时,它应该只是旋转(在同一个线程内),直到得到答案。任何时候要求它并行运行代码......都不要,只要在它的单线程上串联运行即可,等等。
我不是在说只是 await
的任务完成,或调用 Task.Wait()
. 这些不会改变该任务的执行方式。
我强烈认为这种事情并不存在,我只能忍受我的工具没有被很好地架构起来。async
代码。
但如果有这方面的专家,能确认一下就好了。
await
命令,则代码 之后 该 await
在同一条线上继续。但我想要真正的 内容 的 await
在同一个线程上。 请记住,异步!=并行。
具有同步上下文的异步代码可以在一个线程上运行。它开始在一个线程上运行,然后发出一个IO请求(就像HTTP请求一样),当它等待的时候 无事可做. 那么延续(因为有同步上下文)可以根据同步上下文的要求发生在同一个线程上,比如在UI应用中,延续发生在UI线程上。
当没有同步上下文的时候,那么延续 可以 被运行在任何ThreadPool线程上(但仍可能发生在同一个线程上)。
因此,如果你的目标是使它最初运行,然后恢复所有在同一个线程上,那么 你已经得到的答案 确实是最好的方法,因为正是这个同步上下文决定了如何执行延续。
但是,如果有任何对 Task.Run
因为该方法的全部目的是启动一个新的线程(并给你一个异步的方法来等待该线程的完成)。
如果代码使用 .ConfigureAwait(false)
在任何 await
调用,因为这明确意味着 "我不需要在同步上下文上恢复",所以它可能仍然在ThreadPool线程上运行。我不知道Stephen的解决方案是否对此有什么作用。
但如果你真的想让它 "RunAsThoughAsyncDidntExist",并在等待时锁定当前线程,那么这是不可能的。以这段代码为例。
var myTask = DoSomethingAsync();
DoSomethingElse();
var results = await myTask;
这段代码启动了一个IO请求,然后在等待请求结束时做其他事情, 然后结束等待,并在之后处理结果。要想让它表现为同步,唯一的办法就是重构,因为同步的代码不能够在等待的时候做其他工作。必须要决定是在IO请求之前还是之后进行操作 DoSomethingElse()
.