C# 释放互斥锁
我有一个web应用程序需要使用应用程序缓存来存储数据(由于逐个请求获取数据的高开销)。见上一篇文章 这种方法似乎工作得很好,但我发现网站的错误中偶尔会出现以下错误:C# 释放互斥锁,c#,asp.net,caching,mutex,C#,Asp.net,Caching,Mutex,我有一个web应用程序需要使用应用程序缓存来存储数据(由于逐个请求获取数据的高开销)。见上一篇文章 这种方法似乎工作得很好,但我发现网站的错误中偶尔会出现以下错误: System.ApplicationException: Object synchronization method was called from an unsynchronized block of code. at System.Threading.Mutex.ReleaseMutex() at InboxInsight.We
System.ApplicationException: Object synchronization method was called from an
unsynchronized block of code.
at System.Threading.Mutex.ReleaseMutex()
at InboxInsight.Web.Web_Controls.Twitter.TwitterFeed.GetTwitterData(HttpContext context)
at InboxInsight.Web.Web_Controls.Twitter.TwitterFeed.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
以下是代码块供参考:
public string GetData(HttpContext context)
{
var cache = context.Cache;
Mutex mutex = null;
string data = (string)cache[CacheKey];
// Start check to see if available on cache
if (data == null)
{
try
{
// Lock base on resource key
// (note that not all chars are valid for name)
mutex = new Mutex(true, CacheKey);
// Wait until it is safe to enter (someone else might already be
// doing this), but also add 30 seconds max.
mutex.WaitOne(30000);
// Now let's see if some one else has added it...
data = (string)cache[CacheKey];
// They did, so send it...
if (data != null)
{
return data;
}
// Still not there, so now is the time to look for it!
data = GetSlowFeed(context);
cache.Remove(CacheKey);
cache.Add(CacheKey, data, null, GetExpiryDate(),
TimeSpan.Zero, CacheItemPriority.Normal, null);
}
finally
{
// Release the Mutex.
if (mutex != null)
{
mutex.ReleaseMutex();
}
}
}
return data;
}
根据我的研究,它表明这个问题是由一个进程线程试图释放一个它没有创建的互斥锁引起的,但我不明白这是怎么发生的
有人能建议我如何重新构造代码以避免此问题吗?您没有处理mutex.WaitOne返回false ie超时的情况。如果WaitOne返回false,则您不拥有互斥对象,因此不需要释放它
bool iOwnTheMutex;
try {
// set up mutex here...
iOwnTheMutex = mutex.WaitOne(2000);
if (iOwnTheMutex) {
// do what you need to do
}
}
finally {
if (mutex != null && iOwnTheMutex) {
mutex.ReleaseMutex();
}
}
我在你的另一个问题上加了一条评论。然而,这在这里也可能是合适的。存在asp.net的现有缓存提供程序。AppFabric是一个,Memcached是另一个。两人都很擅长他们的工作。到了我不想自己动手的地步。嗨,克里斯,谢谢你的建议。我现在研究了AppFabric和Memcached,但它们似乎不适合我的应用程序,因为它运行在共享托管环境中。作为分布式缓存应用程序,我认为这两个应用程序都需要安装在服务器/操作系统级别,不幸的是,这使得它们无法在该应用程序中使用。这个答案在Metro应用程序中不再适用。如果iOwnTheMutex为true,即使在测试用例中,异常仍然会持续发生。我已经能够通过一个线程(UI)获取/释放互斥,而一个单独的线程(非UI)获取互斥并且无法释放,没有其他线程尝试获取互斥。互斥的主要卖点是进程之间的同步。听起来像是在一个进程中进行同步。我相信你可以找到更适合的方法,最简单的方法就是C#中的
lock
关键字。我认为这不是一个安全的解决方案,因为bool不是线程安全的iOwnTheMutex
是一个局部变量,没有其他线程/进程能够访问它。检查互斥锁是否拥有,然后稍后尝试释放它-这里有一个争用条件。