【问题标题】:C# timer and thread safetyC# 定时器和线程安全
【发布时间】:2011-03-20 01:37:19
【问题描述】:

我有一个带有对象数组的 C# 类,每个对象代表一个与外部设备的开放连接。默认情况下,连接会在我想避免的 n 个空闲小时后超时。我计划使用一个每 n-2 个空闲小时触发一次的计时器,并带有一个回调,该回调调用一个方法来触摸每个对象并有效地重置超时。

该类需要在 Windows 窗体和非基于窗体的项目中都可用,因此我正在考虑使用 System.Timers.Timer 和一个锁来限制任何其他线程在超时重置期间访问数组。

使用计时器会引入线程安全隐患,例如如果其中一个对象在计时器回调确定对象存在和重置其超时之间被破坏,则将尝试读取未初始化的内存。但是,我的问题是在类中的许多地方都可以访问该数组。当定时器回调正在进行时,锁应该阻止对数组的所有访问,如下所示:

class MyClass
{
    private System.Timers.Timer timer;
    private object locker = new object();

    public void Run()
    {
        timer = new System.Timers.Timer();
        timer.Interval = 21600000;  //6 hours
        timer.Elapsed += AccessArrayCallback;
        timer.Start();
    }

    public void AccessArrayCallback(object sender, EventArgs e)
    {

        timer.Enabled = false;
        lock (locker)
        {
            /*  

            if (called by timer) 
            {  
                iterate through array and reset connections;
            }
            else 
            {
                Call appropriate function that reads/writes array using EventArgs delegate   
            }

            */
        }
        timer.Enabled = true;

    }
}

在我继续这种方法之前有几个问题:

  1. 对于这类问题,是否有既定的模式/更优雅的方法?

  2. 在 EventArgs 中使用委托是否正确?类中需要访问数组的任何其他方法都将调用回调并适当地填充 EventArgs。

提前致谢。

【问题讨论】:

    标签: c# synchronization timer


    【解决方案1】:

    由于锁是私有对象,系统的其他部分将无法访问它以达到您想要的线程安全级别。这就是Concurrent Bag 和它的朋友们被创建的原因。委托部分如果没问题的话。

    【讨论】:

    • 感谢您的回答 - ConcurrentBag 看起来不错。这为我节省了很多时间!
    • 我目前使用的是 3.5,它似乎不支持 concurrentBag。我会看一下msdn.microsoft.com/en-us/devlabs/ee794896.aspx,但理想情况下,如果可能的话,我想避免额外的依赖。
    • 哎呀,是的,它是一个框架 4 对象。所需要的只是安装 .net framework 4(如果不是现在,你最终会在未来完成)。
    猜你喜欢
    • 2011-03-04
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    相关资源
    最近更新 更多