【问题标题】:in C# how to run method async in the same thread在 C# 中如何在同一个线程中运行方法异步
【发布时间】:2013-04-21 18:07:37
【问题描述】:

是否可以在与调用者相同的线程中异步定义和调用方法? 假设我只有一个内核,并且不希望有 100 个线程的线程管理开销。

编辑 我问的原因是 nodejs 做事模型 - 一个线程上的所有东西都不会阻塞任何东西,这被证明是非常有效的,这让我想知道在 C# 中是否可以实现相同的东西(我自己无法实现)。

Edit2 好吧,正如 cmets 中所述,节点毕竟不是单线程的(但是简单的负载测试表明,它只使用一个核心......),但我认为是什么让它如此高效是只编写非阻塞代码的隐含要求。这在 C# 中是可能的,除非不是必需的:) 无论如何,谢谢大家...

更多信息在 this SO post 甚至更多 this one

【问题讨论】:

  • @MattBall:假设异步操作不受 CPU 限制。假设异步操作是等待三十秒,然后重置按钮的颜色。为什么要启动另一个线程?
  • @ren:也就是说,Matt Ball 说得有道理。有问题的操作是否需要在另一个线程上运行取决于该操作的实现者。如果要限制创建的线程数,那就是线程池的用途。如果您生成一个异步任务,TPL 将负责从池中调度正确数量的线程以使内核饱和。与其让我们继续猜测您在做什么,不如您就您遇到的实际问题提出问题,而不是提出解决方案。
  • 如果您的问题是“我可以编写一个程序,其中每个操作都是异步的并且每个操作都在同一个线程上吗?”那么答案是肯定的,当然你可以这样做。如果 you 是编写异步操作的人,那么 you 决定它继续执行哪个线程。如果您的问题是“我有一个使用线程池线程的 ComputeFractalAsync 方法,我希望它在当前线程上运行”,那么请致电编写该方法的人并要求他们为您编写一个不使用的版本线程池。
  • nodejs 并不完全是单线程的。 js实际上是同步到事件函数中的,所以你看不到多线程。另请阅读Is NodeJS really Single-Threaded?Node is Not Single Threaded
  • 如果您希望所有调用都在同一个线程上并且您正在编写所有代码,那么永远不要创建新线程。就这么简单。

标签: c# multithreading asynchronous


【解决方案1】:

目前还不清楚你在说什么上下文,但是 C# 5 的 async/await 特性已经有助于支持这种事情。不同之处在于,虽然在 node.js 中,默认情况下所有 强制 都是单线程的(据我了解;很可能错误地给出了 cmets 中的链接),.NET 中的服务器端应用程序使用异步将使用很少的线程,而不会限制自己。如果所有东西真的可以由一个线程提供服务,那很可能 - 如果你在物理处理方面从来没有多过一件事情要做,那很好。

但是如果一个请求进来而另一个请求正在做一些工作怎么办?也许它只是做少量的加密,或者类似的东西。您真的要让第二个请求等待第一个请求完成吗?如果这样做,您可以在.NET 中使用与单线程线程池相关联的TaskScheduler 相当容易地建模...但更常见的是,您会使用内置的线程池到 .NET 中,这将有效地工作,同时仍然允许并发。

首先,您应该确保您使用的是 .NET 4.5 - 它比早期版本的 .NET 具有更多的异步 API(例如用于数据库和文件访问)。您想使用符合 Task-based Asynchronous Pattern (TAP) 的 API。然后,使用async/await,您可以编写服务器端代码,使其读取有点像同步代码,但实际上是异步执行的。例如,您可能有:

Guid userId = await FetchUserIdAsync();
IEnumerable<Message> messages = await FetchMessagesAsync(userId);

即使您需要在每个操作进行时“等待”,但您这样做不会阻塞线程。 C# 编译器负责为您构建状态机。无需显式编写经常变成意大利面条代码的回调 - 编译器会完成所有工作。

您需要确保您使用的任何网络/网络服务框架都支持异步,并且它应该只管理其余部分,使用尽可能少的线程。

按照上面的两个链接了解更多关于 C# 5 中的异步支持的信息 - 这是一个巨大的主题,我相信你之后会有更多的问题,但是当你已经多读一点,您应该能够提出非常具体的问题,而不是当前的宽泛问题。

【讨论】:

  • 对于多线程我真的很想推荐 Joseph Albahari 的 Threading in C#
  • @metadings:这当然是一个很棒的教程——但其中很多内容在异步世界中大部分时间都不需要显式启动新线程甚至新任务。异步和并发当然是相关的,但不是一回事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-23
  • 2020-12-16
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
相关资源
最近更新 更多