首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理后监测多个Threading.Timers

处理后监测多个Threading.Timers
EN

Stack Overflow用户
提问于 2011-06-27 23:59:29
回答 1查看 869关注 0票数 2

我有一个进程,它创建一个动态的定时器列表(System.Threading.Timer),并继续运行直到接收到终止信号为止。一旦接收到终止信号,我希望完成所有现有的计时器回调(请参见下面):

代码语言:javascript
复制
private IList<Timer> _timers = new List<Timer>();
...
...
private void WaitOnExecutingThreads()
{
  var waiters = new List<ManualResetEvent>(_timers.Count);

  foreach (var timer in _timers)
  {
      var onWait = new ManualResetEvent(false);
      waiters.Add(onWait);
      timer.Dispose(onWait);
  }

  WaitHandle.WaitAll(waiters.ToArray());
  waiters.ForEach(x=> x.Dispose());
}

这段代码现在可以工作,但是我希望在释放定时器之后监视正在进行的线程回调。我的目的是在给定的时间间隔内写入日志"Timer A仍在运行“。

我开始玩:

代码语言:javascript
复制
ThreadPool.RegisterWaitForSingleObject(....)

添加以下内容:(注意:我创建了一个包含计时器和相关数据的类ThreadContext )

代码语言:javascript
复制
private void WaitOnExecutingThreads()
{
   var waiters = new List<ManualResetEvent>();

   WaitOrTimerCallback IsRunning = (x, timeout) => { if (timeout) { Log(x + "is still    running"); } };

   foreach (var threadContext in _threadContexts)
   {
      var onWait = new ManualResetEvent(false);
      threadContext.Timer.Dispose(onWait);

      ThreadPool.RegisterWaitForSingleObject(onWait, IsRunning , threadContext.ThreadInfo.Id, new TimeSpan(0, 0, 30), false);

      waiters.Add(onWait);
   }

        WaitHandle.WaitAll(waiters.ToArray());
        waiters.ForEach(x=> x.Dispose());
    }

在C# .net 4.0中,我觉得这应该是一个直接的任务。在我的简单单元测试中,我的IsRunning回调在等待之后触发了很多次。在这个电话之后,我不会再执行任何操作。但是我写了很多我不太习惯的代码,觉得这会失败。

有没有更简单的解决办法,还是我误解了什么?

UPDATE基于Peter .的建议,我提出了以下建议。允许它有更多的代码行,但我不需要注册单个线程对象。如果所有线程在处理后仍在执行,我将休眠10秒,然后再次检查此示例。

代码语言:javascript
复制
    private void WaitOnExecutingThreads()
    {
        foreach (var threadContext in _threadContexts)
        {
            threadContext.DisposeWaiter = new ManualResetEvent(false);
            threadContext.Timer.Dispose(threadContext.DisposeWaiter);
        }

        while(_threadContexts.Count > 0)
        {
            for(var i = 0; i < _threadContexts.Count; i++)
            {
                var threadContext = _threadContexts[i];
                var isComplete = threadContext.DisposeWaiter.WaitOne(0);
                if(isComplete)
                {
                    Console.WriteLine(string.Format("{0}: {1} has completed", DateTime.Now, threadContext.Name));
                    _threadContexts.RemoveAt(i);
                }
                else
                {
                    Console.WriteLine(string.Format("{0}: {1} is still running", DateTime.Now, threadContext.Name));
                }
            }

            if (_threadContexts.Count > 0)
            {
                Thread.Sleep(new TimeSpan(0, 0, 10));
            }
        }
    }
....
public class ThreadContext
{
    public string Name { get; set; }
    public Timer Timer { get; set; }
    public WaitHandle DisposeWaiter { get; set; }
}

_

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-07-11 20:53:47

如果您的处理程序尚未完成,则不会向您的ManualResetEvents发出信号。因此,您可以简单地测试事件是否处于信号状态。即

代码语言:javascript
复制
var isComplete = waiters[0].WaitOne(0);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6500263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档