【问题标题】:Blocking a thread for longer than Int32.MaxValue阻塞线程超过 Int32.MaxValue
【发布时间】:2016-11-16 12:47:27
【问题描述】:

我正在处理一个项目,该项目需要阻塞一个正在运行的线程一段时间,时间跨度可能在一秒到几个月之间变化。

我想出的方法是使用 EventWaitHandle.WaitOne 方法(或其任何同级方法)并指定超时。问题是所有这些方法都将 Int32 作为参数,将最大阻塞时间限制为大约 25 天。

有人知道解决办法吗?如何将线程阻塞更长的 Int32.MaxValue 毫秒?

谢谢

更新

只是为了记录,这是我最终想出的代码sn-p:

while(_doRun)
{
  // Determine the next trigger time
  var nextOccurence = DetermineNextOccurence();
  var sleepSpan = nextOccurence - DateTime.Now;

  // if the next occurence is more than Int32.MaxValue millisecs away,
  // loop to work around the limitations of EventWaitHandle.WaitOne()
  if (sleepSpan.TotalMilliseconds > Int32.MaxValue) 
  {
    var idleTime = GetReasonableIdleWaitTimeSpan();
    var iterationCount = Math.Truncate(sleepSpan.TotalMilliseconds / idleTime.TotalMilliseconds);
    for (var i = 0; i < iterationCount; i++)
    {
      // Wait for the idle timespan (or until a Set() is called).
      if(_ewh.WaitOne(idleTime)) { break; }
    }
  }
  else
  {
    // if the next occurence is in the past, trigger right away
    if (sleepSpan.TotalMilliseconds < 0) { sleepSpan = TimeSpan.FromMilliseconds(25); }

    // Wait for the sleep span (or until a Set() is called).
    if (!_ewh.WaitOne(sleepSpan))
    {
      // raise the trigger event
      RaiseTriggerEvent();
    }
  }
}

那个 sn-p 是由专用线程执行的代码。请注意,EventWaitHandle.Set() 仅在应用程序退出或希望取消调度程序时调用。

感谢那些愿意提供帮助的人。

【问题讨论】:

  • 您真的认为您的应用程序可以运行那么长时间吗?在测试期间它肯定会在第 23 天崩溃
  • 在我看来,设计存在严重问题。
  • 你应该在某个事件上开始你的线程。或者使用不会浪费的定时器来接线程。
  • 线程是工作线程,它们的工作单元以 CPU 周期来衡量。你不会雇佣一个工人然后付钱让他们休眠一万亿秒,所以不要雇佣一个线程并付钱让它休眠一万亿个 CPU 周期。线程不是为长时间运行的事务而设计的;使用不同的机制。
  • @JuiceOntour 是的,但我很有信心地说,任何需要线程可能因 int.MaxValue 或更多而被阻塞的情况都可以重新设计为不需要。

标签: c# multithreading c#-4.0 thread-synchronization


【解决方案1】:

试试handle.WaitOne(System.Threading.Timeout.Infinite)

如果您不希望它无限运行,请从另一个线程外部触发等待句柄。

更新:

如果不想使用其他线程,请使用循环:

bool isTriggered = false;
while (!isTriggered) {
    isTriggered = handle.WaitOne(timeout);
    //Check if time is expired and if yes, break
}

您必须将超时时间跨度拆分为适合Int32 的多个块。 isTriggered 变量将显示句柄是否被触发或超时。

【讨论】:

  • @Sefe 我没有投反对票(反正声望点不够)。但是您提出的解决方法将需要一个不同的线程来了解经过的时间。
  • @JuiceOntour:对不起我的咆哮。无论如何,您确定 TimeSpan 不起作用吗?无论如何,如果您想避免线程,请在循环中等待。查看我的编辑。
  • @Sefe。谢谢。这大概是 Quartz.Net 的人所做的(我刚刚看过): 在循环内部,他们检查等待时间是否在可接受的范围内。如果是,他们会在这个确切的时间阻塞线程。如果不是,他们将线程阻塞半随机时间并再次检查。当然,这是用我的话解释的,而且只用了有限的时间来研究代码。对不起,来自 Quartz.Net 的人,如果我过于简化...
猜你喜欢
  • 2011-03-01
  • 2021-07-07
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
相关资源
最近更新 更多