13

Tôi đang cố gắng sử dụng một mutex cho lần đầu tiên và đã đoạn mã sau thực hiện trên hai trường hợp riêng biệt của chương trìnhAbandoned mutex ngoại lệ

public void asynchronousCode() 
    { 
     using (var mutex = new Mutex(false, "mySpecialMutex")) 
     { 
      if (!mutex.WaitOne(1000, false)) 
      { 
       Console.WriteLine("First check - some one locked the mutex"); 
      } 

      if (!mutex.WaitOne(3000, false)) 
      { 
       Console.WriteLine("Second check- some one locked the mutex"); 
      } 
      else 
      { 
       Console.WriteLine("I got the mutex"); 
       Console.WriteLine("sleeping"); 
       Thread.Sleep(3000); 
       Console.WriteLine("Awaking and Releasing mutex"); 
       mutex.ReleaseMutex(); 
      } 
     } 
    } 

Khi tôi chạy này, một trong những trường hợp (một trong những i chạy đầu tiên) in

I got the mutex 
sleeping 
awaking and releasing mutex 

các bản in dụ khác

First check - some one locked the mutex 

và ngay sau khi inst đầu tiên ance thuê mutex, nó bị treo tại báo cáo kết quả chờ đợi thứ hai ngoại trừ

The wait completed due to an abandoned mutex. 

Bất kỳ ý tưởng về lý do tại sao tôi nhận được ngoại lệ này và làm thế nào tôi có thể ngăn chặn nó?

Giải pháp: Có lẽ tôi đã đọc tài liệu mDSn rõ ràng hơn. Cảm ơn Andrew đã chỉ cho tôi đúng hướng

Bạn có thể sử dụng phương thức WaitHandle.WaitOne để yêu cầu quyền sở hữu một mutex. Các chủ sở hữu một mutex có thể yêu cầu cùng một mutex trong các cuộc gọi lặp đi lặp lại để WaitOne mà không ngăn chặn thực hiện của nó. Tuy nhiên, thread phải gọi phương thức ReleaseMutex cùng một số lần để giải phóng quyền sở hữu của mutex. Lớp Mutex thực thi nhận dạng luồng, do đó, một mutex có thể được phát hành chỉ bởi luồng đã lấy nó.

+2

Lần chạy đầu tiên của bạn đang giữ mutex hai lần, nhưng chỉ phát hành một lần. Do đó, từ bỏ nó. –

Trả lời

19

Vấn đề của bạn là bạn giữ Mutex hai lần, nhưng chỉ phát hành nó một lần, do cách bạn sắp xếp sai các câu lệnh if của mình. Việc thực thi đầu tiên của bạn bắt được nó hai lần - trong cả hai câu lệnh if đó, nhưng mã của bạn chỉ phát hành nó một lần.

Bạn cần phải tổ chức lại if để bạn chỉ ghi lại mutex một lần.

bool captured = true; 
if (!mutex.WaitOne(1000, false)) 
{ 
     Console.WriteLine("First check - some one locked the mutex"); 
     captured = false; 
} 
if (!captured && !mutex.WaitOne(3000, false)) 
{ 
     Console.WriteLine("Second check- some one locked the mutex"); 
     captured = false; 
} 
if (captured) 
{ 
     Console.WriteLine("I got the mutex"); 
     Console.WriteLine("sleeping"); 
     Thread.Sleep(3000); 
     Console.WriteLine("Awaking and Releasing mutex"); 
     mutex.ReleaseMutex(); 
} 
-2

Tôi nghĩ rằng sự cố của bạn bắt nguồn từ dòng using (var mutex = new Mutex(false, "mySpecialMutex")). Khi thread đầu tiên chấm dứt, nó sẽ vứt bỏ đối tượng mutex mà tôi tin là có thể gây ra lỗi mà bạn nhận được.

Nếu có thể, tốt hơn nên khai báo mutex dưới dạng biến lớp tĩnh (static) bên ngoài phương thức đó. Sau đó, bạn sẽ tự khởi tạo nó trước khi bắt đầu chủ đề của bạn và vứt bỏ nó sau khi chúng hoàn tất.

+0

Điều này không chính xác. Các mutex được đặt tên là toàn hệ thống. Đó là việc xử lý mà không phát hành nó gây ra nó có một lỗi thay vì không bao giờ releasingz mặc dù. –

+0

Tôi đã cố gắng tạo biến tĩnh và có chuỗi không kết thúc nhưng tôi đã kết thúc với cùng một ngoại lệ. – nighthawk457