我有这段代码:
var client = new TcpClient();
HttpRequestInfo.AddTimestamp("Connecting");
await Task.WhenAny(client.ConnectAsync(serverAddress, serverPort),
Task.Delay(TimeSpan.FromMilliseconds(300)));
HttpRequestInfo.AddTimestamp("Connected");
if(client.Connected){ ... }
其中HttpRequestInfo.AddTimestamp只是使用Stopwatch类记录命名的时间戳。
在日志中,我有时会看到:
"Connecting":110ms - "Connected":747ms
"Connecting":35ms - "Connected":3120ms
"Connecting":38ms - "Connected":3053ms
我认为这种方法可以让我有机会通过超时(300ms)限制连接。但是,我发现这行代码有时(非常罕见)运行时间超过300毫秒。 这种行为的原因是什么?
答案 0 :(得分:3)
docs州:
此方法取决于系统时钟。这意味着时间 延迟将近似等于系统时钟的分辨率 延迟参数小于系统时钟的分辨率, 在Windows系统上约为15毫秒。
因此,它可以解释超过300毫秒大约15毫秒的超时超时,因为延迟必须根据系统时钟分辨率进行调整。
它不能解释您更长时间的更长时间
我假设由于某种原因,ConnectAsync
可能会在返回调用方法之前阻塞一段时间,如果它是真的,则在第一次登录和实际触发Task.Delay
之间需要一段时间并且问题不是与延迟有关。
您可以尝试使用此代码并监控日志,可能会在启动ConnectAsync
时隐藏丢失的时间:
var client = new TcpClient();
HttpRequestInfo.AddTimestamp("Launching ConnectAsync");
var connectAsyncTask = client.ConnectAsync(serverAddress, serverPort);
HttpRequestInfo.AddTimestamp("ConnectAsync launched");
HttpRequestInfo.AddTimestamp("Launching Delay");
var delayTask= Task.Delay(TimeSpan.FromMilliseconds(300));
HttpRequestInfo.AddTimestamp("Delay launched");
var firstTask = await Task.WhenAny(connectAsyncTask, delayTask);
if(firstTask == connectAsyncTask)
{
HttpRequestInfo.AddTimestamp("Connected");
}
else
{
HttpRequestInfo.AddTimestamp("Timeout");
}