2013-06-12 35 views
5

Tôi có một ứng dụng web cần sử dụng bộ nhớ cache của ứng dụng để lưu trữ dữ liệu (do chi phí cao khi nhận được yêu cầu ona dữ liệu theo yêu cầu). Xem bài trước ở https://stackoverflow.com/a/16961962/236860Phát hành một Mutex

Cách tiếp cận này dường như làm việc tốt, nhưng tôi nhìn thấy các lỗi thỉnh thoảng sau do lỗi trang web của:

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) 

Để tham khảo, đây là khối mã:

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; 
} 

Từ những gì tôi đã nghiên cứu, nó cho thấy vấn đề này được gây ra bởi một luồng quá trình cố gắng để phát hành một Mutex mà nó không tạo ra, nhưng tôi không hiểu làm thế nào điều này có thể xảy ra.

Có ai có thể đề xuất cách tôi có thể cấu trúc lại mã để tránh sự cố này không?

+0

Tôi đã thêm nhận xét vào câu hỏi khác của bạn. Tuy nhiên nó có thể thích hợp ở đây là tốt. Hiện có các nhà cung cấp bộ đệm ẩn cho asp.net. AppFabric là một, Memcached là một. Cả hai đều rất giỏi về những gì họ làm. Đến mức tôi sẽ không bận tâm đến việc lăn mình. – NotMe

+0

Xin chào Chris, cảm ơn lời đề nghị. Bây giờ tôi đã nhìn vào AppFabric và Memcached, nhưng chúng dường như không thích hợp cho ứng dụng của tôi vì nó đang chạy trong môi trường lưu trữ được chia sẻ. Là ứng dụng bộ nhớ cache phân tán, tôi tin rằng cả hai cần phải được cài đặt ở cấp độ máy chủ/hệ điều hành, thật không may, ngăn cản việc sử dụng chúng trong ứng dụng này. – Neilski

Trả lời

13

Bạn không xử lý trường hợp theo đó mutex.WaitOne trả về số lần xuất hiện sai. Nếu WaitOne trả về false bạn không sở hữu mutex, do đó bạn không cần phải giải phóng nó.

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(); 
    } 
}  
+0

Cảm ơn Jack, điều này đã giải quyết được vấn đề. – Neilski

+0

Câu trả lời này không còn hoạt động trong ứng dụng Metro. Ngoại lệ vẫn xảy ra nhất quán, ngay cả trong trường hợp kiểm tra, nếu iOwnTheMutex là đúng. Tôi đã có thể tái tạo với một thread (UI) lấy/phát hành mutex, trong khi một thread riêng biệt (non-UI) lấy mutex và không thể giải phóng nó, không có chủ đề nào khác cố gắng lấy nó. –

+0

Điểm bán hàng chính của Mutex là đồng bộ hóa giữa các quá trình. Có vẻ như bạn đang đồng bộ hóa trong một quy trình. Tôi chắc rằng bạn có thể tìm thấy một cái gì đó phù hợp hơn cho điều đó, đơn giản nhất là từ khóa 'lock' trong C#. –

Các vấn đề liên quan