也就是说,我有一个包含静态System.Threading.Timer的类,我想同步所有对象中的定时器。例如,我想要实现的是让所有对象同时调用DoStuff():
public class TestClass {
public static Timer timer;
public TestClass() {
TimerCallback callback = DoStuff;
timer = new Timer(callback, timer, 0, 500);
}
public void DoStuff(object source) {
// Do stuff
}
}发布于 2017-02-21 01:09:28
因为计时器引用存储在static字段中,所以每次只有一个计时器实例可用。所以我不清楚你所说的“同步定时器复数”是什么意思。
如果您希望类的每个实例在单个计时器的相同勾号上执行其DoStuff()方法,那么在我看来,正确的方法是维护一个静态处理程序,该处理程序调用由每个实例更新的委托实例。例如:
public class TestClass {
private static class TimerHandler
{
public static event TimerCallback TimerHandlers;
private static readonly Timer timer = new Timer(TimerHandlerCallback, null, 0, 500);
private static void TimerHandlerCallback(object state)
{
TimerHandlers?.Invoke(timer);
}
}
public TestClass() {
TimerHandler.TimerHandlers += DoStuff;
}
public void DoStuff(object source) {
// Do stuff
}
}备注:
Timer字段public。timer作为值传递给构造函数的state参数。现在还不清楚你打算在那之前发生什么。下面是发生的事情:第一次初始化计时器时,字段的值是null,所以state参数是null,这就是传递给处理程序的内容。对于TestClass的每个新实例,该实例将创建一个新的计时器,但使用以前创建的timer实例作为state值。在TestClass的每个实例中,当调用其DoStuff()方法时,它将接收对由TestClass对象的前一个实例创建的计时器的引用,或对创建的TestClass对象的第一个实例的null的引用。相反,我只是在没有state值的情况下初始化计时器(传递null),然后在调用委托时传递定时器引用本身。这对我来说比你的代码做的更有意义。
TestClass对象将永远不会被垃圾收集,因为没有从timer事件中取消订阅对象的机制。您可能需要考虑向您的TestClass对象添加一个方法,该方法取消对事件的订阅,并且调用代码可以在它准备丢弃给定的TestClass对象之前调用该方法。是否真的需要这样做,我无从得知。你的问题没有足够的背景。如果这些对象不需要GC‘’ed,那么您可以跳过这个。如果确实需要这样做,您可能需要考虑实现IDisposable作为调用方法的方便机制(即让您的Dispose()方法调用它),这样a)您可以使用using语句来处理对象的生存期,而b)接口实现的存在提醒您需要手动管理对象的生存期。这里关于实现IDisposable的一个警告(除了所有通常的其他警告)是,您将无法依赖终结器作为buggy代码的备份,因为只有当一个对象实际上有资格被GC‘’ed,在这种情况下,只有调用Dispose()时才能工作。
这个问题的另一个替代方法是使用弱引用实现TimerHandlers事件。如果这是在WPF程序的上下文中,则可以使用WeakEventManager类来简化操作。如果不是,您可能会发现学习如何正确使用弱引用是不值得的,特别是在事件的上下文中。再一次,我很难在没有更多背景的情况下说。不管怎样,使用弱引用的好处是事件代码保存的引用本身不会阻止对象被GC‘编辑。您将一个实现细节挑战替换为另一个实现细节挑战;好处是新的挑战是更自动的…。一旦您解决了它,您就完成了,而不是每次创建TestClass对象的实例时都要记住,以后您必须清理它自己。缺点当然是,在概念上,弱引用可能比必须在丢弃对象之前清理对象的基本想法更难理解。
https://stackoverflow.com/questions/42355636
复制相似问题