gpt4 book ai didi

c# - 线程和单例

转载 作者:太空宇宙 更新时间:2023-11-03 19:36:55 27 4
gpt4 key购买 nike

在有人对我发火之前,我会说,在这种情况下,考虑到在我的代码中广泛使用这个对象,我有一个单例是有意义的,如果有人有比 DI 更好的方法,我会很想听,但我希望这不是这篇文章的重点,更多的是帮助解决它。

话虽这么说,但问题是:似乎在给定的时间后,我失去了对我的类(class)调度程序的引用,并且内部有一个不再触发的计时器滴答声。这是因为它以单例方式使用并且一旦失去引用就会被 GC 处理吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace MessageQueueInterface
{
public class Scheduler
{
private const int _interval = 1000;
private readonly Dictionary<DateTime, Action> _scheduledTasks = new Dictionary<DateTime, Action>();
private readonly Timer _mainTimer;

public Scheduler()
{
_mainTimer = new Timer();
_mainTimer.Interval = _interval;
_mainTimer.Tick += MainTimer_Tick;
_mainTimer.Start();
}

void MainTimer_Tick(object sender, EventArgs e)
{
CheckStatus();
}

public void Add(DateTime timeToFire, Action action)
{
lock (_scheduledTasks)
{
if (!_scheduledTasks.Keys.Contains(timeToFire))
{
_scheduledTasks.Add(timeToFire, action);
}
}
}

public void CheckStatus()
{
Dictionary<DateTime, Action> scheduledTasksToRemove = new Dictionary<DateTime, Action>();
lock (_scheduledTasks)
{
foreach (KeyValuePair<DateTime, Action> scheduledTask in _scheduledTasks)
{
if (DateTime.Now >= scheduledTask.Key)
{
scheduledTask.Value.Invoke();
scheduledTasksToRemove.Add(scheduledTask.Key, scheduledTask.Value);
}
}
}
foreach (KeyValuePair<DateTime, Action> pair in scheduledTasksToRemove)
{
_scheduledTasks.Remove(pair.Key);
}
}
}
}

在其他类中是通过以下方式访问的

ApplicationContext.Current.Scheduler.Add(DateTime.Now.AddSeconds(1), ResetBackColor);

ApplicationContext 是我的单例

我也知道 datetime 对象不是字典的最佳 KEY,但它适合我的目的

这是单例

public class ApplicationContext
{
private static ApplicationContext _context;
private Scheduler _scheduler;

public Scheduler Scheduler
{
get { return _scheduler; }
}

private void SetProperties()
{
_scheduler = new Scheduler();
}

public static ApplicationContext Current
{
get
{
if (_context == null)
{
_context = new ApplicationContext();
_context.SetProperties();

}
return _context;
}
}
}

最佳答案

您发布的类似乎不是您的单例类。该代码会更有帮助。

无论如何,是的,如果计时器超出范围并被 GC 处理,那么它将停止触发事件。更有可能的是调度程序立即超出范围,并且在发生这种情况和 GC 发生之间只是有一个延迟。

发布您的单例代码可以让我或其他任何人给出更具体的答案。

编辑

考虑到单例类的简单性,我突然想到的唯一潜在问题是 Current 属性的竞争条件。假设您没有锁定任何东西,那么当 Current 属性为 null 时,两个线程同时访问该属性可能会以不同的引用结束,而最后一个被设置的将是唯一一个有一个引用,其范围将超出属性 getter 本身的范围。

我建议创建一个简单的同步 object 实例作为静态成员,然后将其锁定在 getter 中。这应该可以防止出现这种情况。

顺便说一句,SetProperties() 方法的目的是什么,而不是在无参数构造函数中甚至在声明点初始化变量?拥有这样的功能允许创建一个新的 Scheduler 对象并放弃现有的对象。

关于c# - 线程和单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/976749/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com