tôi có phương pháp này:tuyên bố khóa không xuất hiện để được làm việc
public bool Remove(EntityKeyType key)
{
lock (syncroot)
{
//wait if we need to
waitForContextMRE.Wait();
//if the item is not local, assume it is not remote.
if (!localCache.ContainsKey(key)) return false;
//build an expression tree
Expression<Func<EntityType, bool>> keyComparitorExpression = GenerateKeyComparitorExpression(key);
var itemToDelete = TableProperty.Single(keyComparitorExpression);
//delete from db
TableProperty.DeleteOnSubmit(itemToDelete);
DataContext.SubmitChanges();
//get the removed item for OnCollectionChanged
EntityType itemToRemove = localCache[key];
itemToRemove.PropertyChanged -= item_PropertyChanged;
//remove from the list
Debug.Assert(localCache.Remove(key));
//call the notification
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, itemToRemove));
return true;
}
}
Tôi gọi đó là từ nhiều chủ đề (gọi cùng một ví dụ), nhưng một ngoại lệ tục bị ném vào TableProperty.Single (Sequence chứa không có yếu tố nào). Sau khi gỡ lỗi mã tôi thấy rằng một tình huống đang được tạo ra, nơi các mục đang được xóa khỏi cơ sở dữ liệu sau khi một chủ đề khác nhau đã kiểm tra bộ nhớ cache cho sự tồn tại của nó. Điều này sẽ không thể trừ khi có nhiều luồng bên trong câu lệnh khóa (đối tượng syncroot chắc chắn là cùng một thể hiện trên các luồng).
Không thể? Tôi có bằng chứng:
Có ba chủ đề bên trong tuyên bố khóa! Đưa cái gì?
ghi chú:
- Các GDNCBM được thiết lập (không chặn).
- Đây không phải là trường hợp ngoại lệ bị ném, nó chỉ hiển thị nhiều chuỗi bên trong phần khóa. Cập nhật: Tôi đã thay đổi hình ảnh thành sự kiện intellitrace của ngoại lệ. Hình ảnh cũ là here
- Đối tượng đồng bộ hóa không tĩnh, vì tôi chỉ muốn các cuộc gọi đến cùng một thể hiện được đồng bộ hóa.
Cập nhật
Đây là tuyên bố của đối tượng SyncRoot:
private object syncroot = new object();
Và một số tờ khai khác:
private ManualResetEventSlim waitForContextMRE = new ManualResetEventSlim(true);
private DataContextType _dataContext;
private System.Data.Linq.Table<EntityType> _tableProperty;
//DataContextType and EntityType are generic type parameters
Tôi không thể làm cho SyncRoot tĩnh bởi vì tôi có một số trường hợp của lớp đang chạy và điều quan trọng là chúng không khối k mỗi khác. Nhưng điều đó không thực sự quan trọng - làm cho nó tĩnh không khắc phục được vấn đề.
ManualResetEvent (waitForContextMRE) không có để đồng bộ hóa - ở đó để chặn các thao tác cơ sở dữ liệu trong một thời gian nhất định sau khi thực hiện một số thao tác nhất định (tức là khi khởi động). Nó được đặt hầu hết thời gian. Lấy nó ra khỏi khối khóa cũng không khắc phục được sự cố.
A: chúng ta có thể thấy nơi bạn đang khởi tạo 'syncroot', và B: bao lâu là bối cảnh đối tượng đá xung quanh? C: bạn có chắc rằng họ là cùng một ví dụ? Khó nói với trạng thái tạm dừng ... –
Tôi khuyên bạn nên thêm thông báo dấu vết, với System.Diagnostics.Debug.WriteLine. Viết id luồng và mã băm đồng bộ hóa ở đầu và cuối khối khóa. Sau đó, bạn có thể dễ dàng nhìn thấy trong cửa sổ đầu ra nếu hai chủ đề trùng lặp với cùng một syncroot, mà chắc chắn không nên xảy ra. –
Tác hại trong việc tạo đồng bộ hóa tĩnh là gì? –