我正在考虑在具有事件驱动逻辑的 MMO 游戏服务器中使用 C# 异步等待。让我们假设有数千个实体在已知持续时间内做一些工作。所以我想为我的每个游戏对象调用
Time.Delay()
。 (这是与普通无限循环相反的方法,每个游戏对象都有一些Update()
调用。)
有人知道
Task.Delay()
是如何实现的吗?
它使用定时器吗?系统资源占用大吗?
是否可以同时产生数千个
Task.Delay()
调用?
Task.Delay
实现如下:
public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
{
//error checking
Task.DelayPromise delayPromise = new Task.DelayPromise(cancellationToken);
if (cancellationToken.CanBeCanceled)
delayPromise.Registration = cancellationToken.InternalRegisterWithoutEC((Action<object>) (state => ((Task.DelayPromise) state).Complete()), (object) delayPromise);
if (millisecondsDelay != -1)
{
delayPromise.Timer = new Timer((TimerCallback) (state => ((Task.DelayPromise) state).Complete()), (object) delayPromise, millisecondsDelay, -1);
delayPromise.Timer.KeepRootedWhileScheduled();
}
return (Task) delayPromise;
}
它肯定使用定时器。它们用于名为
DelayPromise
的类中。这是它的实现:
private sealed class DelayPromise : Task<VoidTaskResult>
{
internal readonly CancellationToken Token;
internal CancellationTokenRegistration Registration;
internal Timer Timer;
internal DelayPromise(CancellationToken token)
{
this.Token = token;
}
internal void Complete()
{
if (!(this.Token.IsCancellationRequested ? this.TrySetCanceled(this.Token) : this.TrySetResult(new VoidTaskResult())))
return;
if (this.Timer != null)
this.Timer.Dispose();
this.Registration.Dispose();
}
}
它确实使用了计时器,但我似乎并不担心。计时器只是回调到 complete 方法,它所做的是检查它是否被取消,如果是则取消它,否则只返回一个结果。对我来说似乎很好。
在 .NET Core 中,
Task.Delay
是通过 TimerQueue
实现的。它不会每次都创建一个新的Timer
。从我从 源代码 中可以看出,它创建了 N 个“队列”,其中 N 是 CPU 内核的数量。然后它为每个队列使用 1(一)个本机非托管操作系统计时器。
这比 .NET Framework 方法更轻量级,但每次调用
Task.Delay
时仍然会执行大量代码。我希望有更好的方法。
附言只是为谷歌搜索者添加了一个更新的版本。