Asp.Net. Synchronization access(mutex)

坚强是说给别人听的谎言 提交于 2019-12-11 05:08:45

问题


for synchronizing access to my NHibernate session at web environment I try use Mutex:

public class FactoryRepository
{
    private FactoryRepository() { }
    private static Mutex _sessionMutex = new Mutex();
    private static ISessionFactory factory;
    public static ISessionFactory SessionFactory
    {
        get
        {
            factory = factory ?? new Configuration().Configure().BuildSessionFactory();
            return factory;
        }
    }

    public static ISession Session
    {
        get
        {
            ISession currentSession;
            _sessionMutex.WaitOne();
            if (HttpContext.Current != null)
            {
                HttpContext context = HttpContext.Current;
                currentSession = context.Items[SessionKey] as ISession;
                if (currentSession == null || !currentSession.IsOpen)
                {
                    currentSession = SessionFactory.OpenSession();
                    context.Items[SessionKey] = currentSession;
                }
            }

            _sessionMutex.ReleaseMutex();
            return currentSession;

        }
    }
}

At my error logging I get:

System.Threading.AbandonedMutexException: The wait completed due to an abandoned mutex.
Method: Boolean WaitOne(Int64, Boolean)

Stack Trace:

 at System.Threading.WaitHandle.WaitOne(Int64 timeout, Boolean exitContext)
 at System.Threading.WaitHandle.WaitOne(Int32 millisecondsTimeout, Boolean exitContext)
 at System.Threading.WaitHandle.WaitOne()

Why do I get this exception with calling ReleaseMutex();


回答1:


Your issue is on this line

 _sessionMutex.WaitOne();

The WaitOne() can throw this exceptions because some other thread that lock it, exit with out releasing it

In your case the WaitOne throw this exception because of an abandon of the same mutex in an other thread.

I suggest to warp your mutex in a class and use a code like:

            try
            {
                cLock = _sessionMutex.WaitOne();
                // call your work
            }
            catch (AbandonedMutexException)
            {
                cLock = true;
                // call your work
            }
            catch (Exception x)
            {
                //Error
            }
            finally
            {
               _sessionMutex.ReleaseMutex();
            }

In the above code the ReleaseMutex may fail to run if a user stop/abandon the page and the thread is lost/delete it. And thats why you get this exception.

Be ware that mutex can lock for ever the way you do it ! :) Its better to add a millisecond limit on the wait, and / or handle the case of non lock to return read only data. You users can lock for long time if the mutex fails to pass the WaitOne()

Also be ware, the Mutex need to be close and dispose. ! Even if this is like the example in MSDN, in MSDN is only an simple Example, you need to be sure that you close and dispose your Mutex or else you see more problems when you update your page. For example if the Mutex stay on memory locked wile you update your page, then your page may lock for long time, until the Garbage collection kill it, if they do.




回答2:


Unless you're using a very old version of NHibernate, I think this is probably overkill. NHibernate already has the ability to give you contextual session management in a web environment, and I think it will manage things more reliably for you.

Take a look at section 2.3 of this: NHibernate Chapter 2 - Architecture




回答3:


Windows O/S has long had a bug where locking one mutex inside another could lock both if they are not unlocked properly in the correct reverse sequence.

Basically the race condition and locking could be due to NHibernate using a mutex to lock the resource as well as the mutex you are using.



来源:https://stackoverflow.com/questions/6775382/asp-net-synchronization-accessmutex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!