如何使这个线程安全

Posted

技术标签:

【中文标题】如何使这个线程安全【英文标题】:How to make this thread-safe 【发布时间】:2011-07-18 05:08:07 【问题描述】:

我有以下用于 Fluent NHibernate 的 SessionFactory。

我收到一个错误

创建 SessionFactory 时使用了无效或不完整的配置。

InnerException 为

已添加具有相同密钥的项目。

这个问题只是偶尔发生,我的应用程序大部分时间都可以正常工作。

基于NHibernate: System.Argument Exception : An item with the same key has already been added 我猜我的类不是线程安全的,这可以解释这个错误的间歇性。

using System;
using NHibernate;
using NHibernate.Cache;
using NHibernate.Cfg;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using WSS.Data.Domain;

namespace WSS.Data 
    public static class SessionFactory 
        private static ISessionFactory _factory = null;
        private static ISessionFactory GetFactory() 
            if (_factory == null) 
                NHibernate.Cfg.Configuration config;
                config = new NHibernate.Cfg.Configuration();
                config.Configure();
                if (config == null) 
                    throw new InvalidOperationException("NHibernate configuration is null.");
                


                config.AddAssembly("WSS.Data");
                _factory = config.BuildSessionFactory();
                if (_factory == null) 
                    throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
                
            
            return _factory;

        

        private static ISessionFactory GetFluentFactory() 
            if(_factory == null) 
                _factory = Fluently.Configure()
                    .Database(MsSqlConfiguration.MsSql2000
                        .ConnectionString(c => c
                            .Is(ConnectionStrings.Auto))
                        .Cache(c => c
                            .UseQueryCache()
                            .ProviderClass())
                        .ShowSql())
                    .Mappings(m => m
                        .FluentMappings.AddFromAssemblyOf())
                    .BuildSessionFactory();
            

            return _factory;
        

        public static ISession OpenSession() 
            ISession session;
            session = GetFluentFactory().OpenSession();
            if (session == null) 
                throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
            
            return session;
        
    

【问题讨论】:

【参考方案1】:

通常的方法是创建一个只允许单次访问的互斥体(可能在您的公共方法中)。见http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx

未测试为编译,但类似:

    private static Mutex _sessionMutex = new Mutex();

    public static ISession OpenSession() 
        ISession session;

        _sessionMutex.WaitOne();

        session = GetFluentFactory().OpenSession();
        if (session == null) 
            throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
        

        _sessionMutex.ReleaseMutex();
        return session;
    

【讨论】:

谢谢,我试试看。 @IamStalker:什么不起作用?使用演示问题的代码发布一个新问题。另一种可行的方法是使用“锁定”,但这仅适用于单个进程(及其线程),而不适用于系统范围。

以上是关于如何使这个线程安全的主要内容,如果未能解决你的问题,请参考以下文章

使函数线程安全的类

如何使 ObservableCollection 线程安全?

如何使 Stack.Pop 线程安全

如何轻松使 std::cout 线程安全?

如何使 Swift 类单例实例线程安全?

使用来自其他类的公共静态 HashTable 的同步方法。我怎样才能使这个方法线程安全?