【问题标题】:Does Timer.Change() ever return false?Timer.Change() 会返回 false 吗?
【发布时间】:2012-09-17 04:56:01
【问题描述】:

.NET System.Threading Timer 类有几个重载的 Change() 方法,如果成功更新计时器,则返回“true;否则,返回 false”。

参考:http://msdn.microsoft.com/en-us/library/yz1c7148.aspx

这个方法真的会返回 false 吗?什么会导致它返回 false?

【问题讨论】:

  • 如果你返回false,例如。使用相同的值设置两次。
  • 这很奇怪,当我第二次尝试设置相同的参数时,我可以在 LinqPad 中看到相同的计时器返回 false,我将进一步研究它。

标签: c# .net multithreading timer


【解决方案1】:

Joe Duffy(Parallel 的开发主管、架构师和创始人 Microsoft .NET Framework 团队的扩展)在 Windows 上的并发编程 p 373

中有详细说明

请注意,尽管Change 被输入为返回bool,但它实际上不会返回任何内容,而是真实的。如果更改定时器出现问题——例如目标对象已经被删除——将抛出异常。

【讨论】:

    【解决方案2】:

    如果非托管外部 ChangeTimerNative 返回 false,这实际上会返回 false。但是,这极不可能。

    注意微软的代码:

    bool status = false;
    bool bLockTaken = false; 
    
    // prepare here to prevent threadabort from occuring which could
    // destroy m_lock state.  lock(this) can't be used due to critical
    // finalizer and thinlock/syncblock escalation. 
    RuntimeHelpers.PrepareConstrainedRegions();
    try 
    { 
    }
    finally 
    {
        do
        {
            if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) 
            {
                bLockTaken = true; 
                try 
                {
                    if (timerDeleted != 0) 
                        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic"));
                    status = ChangeTimerNative(dueTime,period);
                }
                finally 
                {
                    m_lock = 0; 
                } 
            }
            Thread.SpinWait(1);     // yield to processor 
        }
        while (!bLockTaken);
    }
    return status; 
    

    请注意ChangeTimerNative 调用ChangeTimerQueueTimer Windows API 函数,因此您可以阅读该文档以了解它可能会如何失败。

    【讨论】:

    • 没有显示 ChangeNativeTimer 的详细信息,这与 Timer.Change() 的文档没有什么不同。
    • @RichAmberale: ChangeTimerNative 调用这个:msdn.microsoft.com/en-us/library/windows/desktop/…,仍然没有提供任何有用的线索。
    • @mike 你怎么知道ChangeTimerNative 打电话给ChangeTimerQueueTimer
    • @PeterRitchie,对反射器的一些工作和一些验证意见。 :)
    • @PeterRitchie:很公平,我的意思不是你知道什么,而是你在这个世界上认识的朋友。我想这只是使我的答案无效吧?
    【解决方案3】:

    在检查托管源时,它返回 false 的唯一情况是,如果由私有类 AppDomainTimerSafeHandle 表示的 AppDomain 计时器(如果不存在,则创建它)将 SafeHandle.IsInvalid 设置为 true。

    由于 AppDomainTimerSafeHandle 继承自 SafeHandleZeroOrMinusOneIsInvalid,因此 IsInvalid 由它实现 - 当非托管基础架构尝试创建计时器并以从零或减一定义中读取的安全句柄结束时-Is-Invalid。

    所有案例都表明这是极不可能的。

    【讨论】:

    • 你说的是Change 方法还是别的什么? Change 不创建计时器...
    • @PeterRitchie 它相当于 Timer 队列中的一个条目。我已经对其进行了编辑以使其更清晰。
    • @PeterRitchie 我想我应该在downvotefags出现之前删除这个答案。
    • 目前还不清楚这如何应用于Change 方法。
    • @PeterRitchie 我没有理由编造这个。我们很可能正在研究同一事物的两种实现。您最有可能在查看System.dll
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多