【问题标题】:Why does waiting on this Task for 1022 milliseconds work fine but 1023 causes an AggregateException?为什么等待此任务 1022 毫秒工作正常但 1023 会导致 AggregateException?
【发布时间】:2012-06-13 01:12:53
【问题描述】:

尝试实现连接服务器的超时参数,但我运气不佳。这是我的代码:

client = new TcpClient();

Task task = Task.Factory.FromAsync(client.BeginConnect, client.EndConnect, host, port, null);

bool taskCompleted = connectTask.Wait(timeoutInMS);

if (taskCompleted)
{
    // Do something with the establishment of a successful connection
}
else
{
    Console.WriteLine("Timeout!");
}

很遗憾,如果 timeoutInMS 大于 1022,则会在此行抛出 AggregateException:

bool taskCompleted = connectTask.Wait(timeoutInMS);

调整 TcpClient 的超时属性似乎没有任何区别。

【问题讨论】:

  • 聚合的InnerExceptions 是什么?
  • @FrédéricHamidi: "No connection could be made because the target machine actively refused it 127.0.0.1:8080"
  • 超时小于1023秒是连接成功,还是在所有情况下总是被拒绝?
  • @FrédéricHamidi:如果超时时间小于 1023 秒,则不会引发错误。但是,连接也不成功,因为服务器没有运行。

标签: c# android android-asynctask tcpclient waithandle


【解决方案1】:

很可能是因为Task 在 1022 毫秒内还没有产生结果。但稍等片刻,任务就能够捕获TcpClient抛出的SocketException。

您的情况类似于以下:

var task = Task.Factory.StartNew(() =>
{
  Thread.Sleep(5000);
  throw new Exception();
});

bool taskCompleted = task.Wait(4000); // No exception
bool taskCompleted = task.Wait(6000); // Exception

顺便问一下,当您以同步方式使用TcpClient 时,为什么还要使用FromAsync()?

【讨论】:

  • 这个例子有点做作。在我目前的实际代码中,我没有调用 Wait,在调用 FromAsync 之后,我调用了task.ContinueWith(...);。您知道允许使用任务实现自定义超时的解决方案吗?
  • @Ryan, this question 那么你可能会感兴趣。
  • 我不知道在 TPL 中有一种优雅的方式来做到这一点。但我认为通常实现的是记录您提出请求的时间(可能是StopWatch?),然后在您的任务继续中获取经过的时间。如果经过的时间大于您的超时时间,则不要继续请求,如果需要,可以关闭NetworkStream。
  • @FrédéricHamidi 该解决方案可能有效。但请注意,它会阻塞 ThreadPool 线程。人们失去了使用等待 I/O 完成端口的 BeginConnect/EndConnect 的优势。
  • @IlianPinzon:你觉得第二个回复怎么样?创建一个工作线程和一个超时线程,启动它们,然后使用Task.WaitAny 找出哪个先完成。我唯一担心的是它基本上使传入连接的线程池线程数量增加了一倍(不确定这是否是过早的优化。你怎么看?)
猜你喜欢
  • 1970-01-01
  • 2012-08-14
  • 2021-08-24
  • 2016-10-20
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 2017-11-11
  • 2021-12-30
相关资源
最近更新 更多