是否有一种巧妙的方法,迫使一堆 "async "C#代码以单线程方式运行,仿佛它实际上不是 "async "的。

问题描述 投票:-1回答:1

假设(完全是假设性的;))我有一大堆的 async 代码。

10s的类;100s的异步方法,其中有10s是 其实 做异步工作(例如,在我们 WriteToDbAsync(data) 或者我们 ReadFileFromInternetAsync(uri)或当 WhenAll(parallelTasks).

我想对它进行一系列的诊断调试。我想对它进行灌注剖析,并手动地检查它,看看什么是什么。

我所有的工具都是围绕同步的C#代码设计的。它们将 某种 搭配 async但它的效果肯定要差很多,而且调试起来也很困难,即使我尝试直接管理一下线程。

如果我只对一小部分代码感兴趣,那么暂时解除async 的那部分代码。同步读写,只需在我的每一个 "并行 "的Task.Wait() Task的顺序。但如果我想在大量的代码中摸索,那是不可行的。

有没有办法让C#运行一些"async"这样的代码给我?

即某种 (() => MyAsyncMethod()).RunAsThoughAsyncDidntExist() 它知道,任何时候它与外界进行真正的异步通信时,它应该只是旋转(在同一个线程内),直到得到答案。任何时候要求它并行运行代码......都不要,只要在它的单线程上串联运行即可,等等。

我不是在说只是 await的任务完成,或调用 Task.Wait(). 这些不会改变该任务的执行方式。


我强烈认为这种事情并不存在,我只能忍受我的工具没有被很好地架构起来。async 代码。

但如果有这方面的专家,能确认一下就好了。


EDIT:(因为SO让我解释一下为什么这个建议不是答案)......Sinatr建议这样做。 我如何创建一个自定义的同步上下文 让所有的延续都能被我自己的单线程事件循环处理? 但是(根据我的理解)这将确保每次有一个 await 命令,则代码 之后await 在同一条线上继续。但我想要真正的 内容await 在同一个线程上。
c# multithreading asynchronous task-parallel-library
1个回答
1
投票

请记住,异步!=并行。

  • 并行意味着同时运行两段或多段代码,这只能通过多线程来实现。这是关于代码如何 运行.
  • 异步代码释放了当前线程,让它在等待其他事情的时候做其他事情。它是关于代码如何 等待.

具有同步上下文的异步代码可以在一个线程上运行。它开始在一个线程上运行,然后发出一个IO请求(就像HTTP请求一样),当它等待的时候 无事可做. 那么延续(因为有同步上下文)可以根据同步上下文的要求发生在同一个线程上,比如在UI应用中,延续发生在UI线程上。

当没有同步上下文的时候,那么延续 可以 被运行在任何ThreadPool线程上(但仍可能发生在同一个线程上)。

因此,如果你的目标是使它最初运行,然后恢复所有在同一个线程上,那么 你已经得到的答案 确实是最好的方法,因为正是这个同步上下文决定了如何执行延续。

但是,如果有任何对 Task.Run因为该方法的全部目的是启动一个新的线程(并给你一个异步的方法来等待该线程的完成)。

如果代码使用 .ConfigureAwait(false) 在任何 await 调用,因为这明确意味着 "我不需要在同步上下文上恢复",所以它可能仍然在ThreadPool线程上运行。我不知道Stephen的解决方案是否对此有什么作用。

但如果你真的想让它 "RunAsThoughAsyncDidntExist",并在等待时锁定当前线程,那么这是不可能的。以这段代码为例。

var myTask = DoSomethingAsync();
DoSomethingElse();
var results = await myTask;

这段代码启动了一个IO请求,然后在等待请求结束时做其他事情, 然后结束等待,并在之后处理结果。要想让它表现为同步,唯一的办法就是重构,因为同步的代码不能够在等待的时候做其他工作。必须要决定是在IO请求之前还是之后进行操作 DoSomethingElse().

© www.soinside.com 2019 - 2024. All rights reserved.