C# 有点像单件工厂

C# 有点像单件工厂,c#,object-lifetime,C#,Object Lifetime,很抱歉,如果其他地方已回答此问题。。。我发现了很多关于类似事情的帖子,但不尽相同 我希望确保一次只存在一个对象的实例,但我不希望该对象在其自然生命周期之后被保留,因为它可能是单例模式 我正在编写一些代码,其中列表的处理每分钟都会被触发(由我无法控制的外部代码触发)。目前,我每次只是创建一个新的“处理”对象,当它超出范围时,它就会被销毁,这与正常情况相同。但是,有时处理时间可能超过一分钟,因此下一个触发器将在新线程中创建处理类的第二个实例 现在,我想有一个机制,一次只能有一个实例。。。比如说,某种

很抱歉,如果其他地方已回答此问题。。。我发现了很多关于类似事情的帖子,但不尽相同

我希望确保一次只存在一个对象的实例,但我不希望该对象在其自然生命周期之后被保留,因为它可能是单例模式

我正在编写一些代码,其中列表的处理每分钟都会被触发(由我无法控制的外部代码触发)。目前,我每次只是创建一个新的“处理”对象,当它超出范围时,它就会被销毁,这与正常情况相同。但是,有时处理时间可能超过一分钟,因此下一个触发器将在新线程中创建处理类的第二个实例

现在,我想有一个机制,一次只能有一个实例。。。比如说,某种工厂,一次只允许一个对象。对工厂的第二次调用将返回null,而不是一个新对象,例如

到目前为止,我的(糟糕的)解决方案是将Factory类型对象作为processor类的嵌套类:

class XmlJobListProcessor
{
    private static volatile bool instanceExists = false;

    public static class SingletonFactory
    {
        private static object lockObj = new object();

        public static XmlJobListProcessor CreateListProcessor()
        {
            if (!instanceExists)
            {
                lock (lockObj)
                {
                    if (!instanceExists)
                    {
                        instanceExists = true;
                        return new XmlJobListProcessor();
                    }
                    return null;
                }
            }
            return null;
        }
    }

    private XmlJobListProcessor() { }
    ....
    }
我正在考虑为XmlJobListProcessor类编写一个显式析构函数,将“instanceExists”字段重置为false

我意识到这是一个非常糟糕的设计。工厂本身应该是一个阶级。。。它是嵌套的,这样它和实例析构函数都可以访问volatile boolean


有没有更好的方法?干杯

只要做一个并保持它,不要每分钟都破坏和创造它


“最小化移动部件”

我将实例化该类并将其保留。当然,我不会使用会增加GC时间的析构函数(如果您是指~myInstance())。此外,如果一个进程花费的时间超过一分钟,那么如果您只返回一个空值,您将如何处理假定要处理的数据

使实例保持活动状态,并可能构建一个缓冲区机制,以便在处理器类繁忙时继续获取输入。您可以查看:

if ( isBusy == true )
{
     // add data to bottom of buffer
}
else
{
     // call processing
}

我接受了每个人关于不重新实例化处理器对象的观点和BillW关于队列的观点,因此这里是我的bastardized mashup解决方案:

public static class PRManager
{
    private static XmlJobListProcessor instance = new XmlJobListProcessor();
    private static object lockobj = new object();

    public static void ProcessList(SPList list)
    {
         bool acquired = Monitor.TryEnter(lockobj);
            try
            {
                if (acquired)
                {
                    instance.ProcessList(list);
                }
            }
            catch (ArgumentNullException)
            {
            }
            finally
            {
                Monitor.Exit(lockobj);
            }
    }
}
处理器作为静态成员长期保留(这里,长期对象保留不是问题,因为它没有状态变量等)。如果在lockObj上获得了锁,请求就不会被处理,调用线程将继续其业务


为反馈人干杯。Stackoverflow将确保我的实习;D

您最初的示例使用双重检查锁定,这应该不惜一切代价避免


请参阅如何正确初始化Singleton。

我知道.NET 4的使用并不广泛,但最终它会得到广泛应用,您将拥有:

private static readonly Lazy<XmlJobListProcessor> _instance =
    new Lazy<XmlJobListProcessor>(() => new XmlJobListProcessor());
private static readonly Lazy\u实例=
新的惰性(()=>新的XmlJobListProcessor());

然后您可以通过
\u instance.Value
访问它,它在第一次被请求时被初始化。

为什么只需要创建一个对象就需要创建一个完整的工厂?为什么不重写InitializeLifeTime以返回null以保持它的“活动状态”?@Pierre-“工厂”可能是一个用词不当-其思想是将一个类的实例数限制为一个,即使可能有多个线程尝试同时创建它们。并在不保留对该对象的任何引用的情况下执行此操作,这样它就可以拥有正常的作用域内-作用域外生存期。假设:您希望一次处理一个任务的一个原因是处理列表的每一轮都会更改列表内容:因此多线程不可用。免责声明:这是一个我没有重大经验的领域,因此请恕我直言,请原谅一个可能相当无知的问题:但是,在这里对任务排队的想法是否有一种自然的“共鸣”?一次处理一个任务的原因是任务类具有依赖性,它们有自己的依赖关系。。。。其思想是防止不必要地使用服务器资源。一次一个就可以了。你是对的;队列确实是一种想法,但可能不接受“重复任务”(因为它们都是相同的任务,不需要排队),或者容量为1。我想这确实是限制服务器上资源使用的一种糟糕方式。我想将实例的数量限制为一个,但要确保一次只在一个线程中使用它(因为处理过程可以每分钟触发一次),这就是为什么我想要避免单例模式。。。我确实希望一次只访问一个实例,但一次只能访问一个线程。。。工厂的想法很简单,就像“如果一个实例已经存在,你就不能有另一个实例……再过一分钟再回来,然后再尝试……”。此外,通过在不需要的时候不保留实例(这可能是每分钟周期的约70%),内存会被释放用于其他事情。我无法想象你会“释放”太多。把它想象成停车和启动汽车。与连续停车和启动相比,您可以让车辆怠速运行更长的时间。类似的说法是,停止和开始某件事需要“更多的工作”。每次你杀死实例时,它都会受到GC的仔细检查……这就需要GC花时间做一些“更重要的事情”。@[Olong singy]:在大多数现代平台上,内存分配和销毁是最昂贵的操作。除非您的单例占用了数兆字节(甚至可能占用了!),否则您最好让它闲置。如果单线程是主要关注点,那么使用信号量或lock.Hmmm,看起来您与上面的观点类似。。。一切都很好至于“如果您只返回一个空值,您将如何处理假定要处理的数据?”。。。没有数据,这更像是“执行相同的任务X,如果它还没有运行”,在哪里p