【问题标题】:Thread Throttling in C#C#中的线程节流
【发布时间】:2012-08-06 01:02:03
【问题描述】:

我在 VS2010 中使用 C# 中的 VB .NET 4 创建了一个游戏。游戏为每个玩家创建一个线程,并运行玩家创建的 LUA 代码。

每个 LUA 代码都为线程阻塞,并且只应在线程终止时终止(LUA 脚本应包含无限循环)

我想限制 CPU 使用率,因为计算机在以 100% CPU 运行几个小时后当前过热。

如何在不控制线程的情况下限制线程?我希望有一个线程管理器来强制挂起/恢复,但这些已经过时了,我不想抛出异常,因为这会中止我正在执行的 LUA 代码。

有什么想法吗?

谢谢!

【问题讨论】:

  • 你能让你的 C-Sharp 代码调用一个本质上是你的主循环的方法吗?我不确定 LUA 是否具有高分辨率计时器(我假设您正在将其用于您的游戏逻辑),但 C-Sharp 肯定有,因此您在 LUA 中的主要方法可能会接受帧之间的增量而不是自己计算。
  • 目前的工作方式是所有游戏逻辑都在 C-Sharp 中完成。 LUA 线程能够通过同样可以在 LUA 中调用的 .NET 函数(一种函数映射)来获取有关游戏的信息,并将控制信息返回给游戏。我不确定我是否理解您的问题,这有帮助吗?
  • 我的印象是 LUA 将完成大部分游戏逻辑。如果 C-Sharp 执行逻辑,LUA 会添加什么?
  • 将 LUA 视为玩家的控制器。游戏继续进行,玩家提交的 LUA 代码将观察和控制他们在游戏中关联的玩家。
  • 对我来说,我会尝试将所有逻辑集中在一个地方(语言),这样您就不必担心同步和编组数据。

标签: c# multithreading visual-studio-2010 throttling


【解决方案1】:

您可以将这些线程的线程优先级设置为低 - 这将有助于您的系统保持响应...但是您仍然会使用 100% 的 CPU 并且仍然会过热,因此我不会详细说明如何设置。

正如其他海报所提到的,您需要让线程插入小睡眠。如果您根本无法控制它们,那么您将无能为力。

我建议您需要更改游戏 API。

与其让你的代码一次调用 Lua 代码,然后 Lua 代码无限循环,我建议你让 Lua 代码具有“运行一帧”功能。然后将无限循环移动到自己的代码中,并重复调用“运行一帧”函数。

这样,您可以插入睡眠、添加日志记录以及做各种其他有用的事情。

【讨论】:

  • +1 用于无限循环上的定时帧。 Flash 播放器这样做效果很好。
  • @spender 就此而言,Windows 也是如此。
  • 我在某种程度上喜欢这种方法,但是如果我不断地中断线程并重新启动它,LUA 环境就会被破坏,因此用户维护状态的能力有限。我相信我要做的是添加一个 LUA 脚本可以调用的函数,这会导致 .NET 线程休眠。我可以监控自上次调用以来已经过了多长时间,如果用户运行“热”,我可以关闭线程,休眠很长时间,然后重新启动线程。这迫使用户对我认为的处理保持合理。我会试一试。
  • 我补充说,当用户调用提供反馈的方法(至少每个周期应该一次)时,会有一个小的睡眠。到目前为止,这已经极大地提高了性能,但在不调用此函数的情况下无助于无限循环。
  • 我已经使用这里提出的一些想法充分解决了这个问题。当用户调用控制器函数或睡眠函数时(在他们可能正在执行一个较长的过程但尚未决定执行哪个操作的情况下)一个计时器被重置。主游戏引擎在每次运行时都会检查此计时器,如果计时器超过一定数量,则线程将被杀死,然后在长时间休眠后重新启动。即使玩家不断锁定,CPU 似乎也不会承受太大压力。现在大部分 CPU 都由游戏线程使用,但仍低于 30%。非常感谢!
【解决方案2】:

确保无限循环中的线程不会消耗太多 cpu 的典型方法是让它在每次迭代中休眠一点(通常 5 毫秒就可以了)。这将使系统有时间允许其他资源使用 cpu。另外,不要给线程最高优先级。

【讨论】:

  • 不确定如果“LUA 代码阻塞线程”会有多大帮助。我假设这意味着 LUA 代码正在执行,你不能调用 Thread.Sleep()。
  • @Peter 我说的是“LUA 脚本应该包含一个无限循环”部分。包含无限循环的代码应该调用 sleep 函数。
  • 顺便说一句。 Thread.Sleep 具有由系统“量子”定义的粒度。 Sleep(5) 基本上永远不会发生。根据系统的不同,它可能相当于 Sleep(20)。如果您有一个循环的 CPU 绑定线程,您可以使用 Thread.Sleep(1) 将 CPU 让给其他线程。如果您没有循环或没有特定点可以调用 Thread.Sleep,则此 Sleep 概念将不起作用。
  • 我不能从线程中调用 sleep,LUA 代码阻塞了,是的。我可以从与玩家一起进行游戏计算的引擎管理器访问线程,这个线程可以限制其他线程吗?还是我只能从内部睡一个线程?
  • @Jonathan LUA 是一种不同的编程语言。它无法调用 .NET Thread.Sleep()。我不知道它是否甚至具有“睡眠”线程的能力。如果没有,这个概念就行不通。
【解决方案3】:

控制执行线程调度的经典方法是使用 Fibers。

但是,Fibers 是 WIN32 API 的本机功能....在 C# 中最接近的方法是使用迭代器...在每个产量之间您可以做一些工作...但您决定何时希望通过调用迭代器来完成下一点工作。

请参阅第二个链接...可能是一种使用非托管本机 Fiber API 来包装一些 .NET 协程的方法,或者如果您在此线程中运行的 LUA 代码是本机的并且您无权访问源代码代码...那么您也许可以使用 ConvertThreadToFibre 来控制它(并决定何时使用 Fiber API 调用的一些互操作来安排它)。

或者你可以有一个调度线程,它使用事件向玩家线程发出信号,当他们可以继续并做一些工作时(如果你的一些代码是本机/C++,一些是 C#,那么每个都可以引用相同的事件句柄....只需在每一位代码中使用 WIN32API 或 .NET API)。

【讨论】:

  • 但不幸的是 C#/.NET 没有纤程。
猜你喜欢
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
  • 2011-12-07
  • 1970-01-01
  • 2020-09-03
  • 1970-01-01
  • 2012-08-21
相关资源
最近更新 更多