我有一個類,其中包含(其中包括許多其他內容)需要儘可能經常保存到磁盤的項目列表。爲了做到這一點,無論何時做出任何改變,它都會使用一個定時器來延遲半秒的存儲時間,如果在半秒鐘之內發生任何進一步的改變,它會延遲定時器;換句話說,只要半秒內沒有變化,它就會保存到磁盤中。在單獨的線程上處理保存
但是,我遇到線程問題,其中列表可以在保存中修改。我想出了一個修復它的方法,但是感覺有點像黑客,而且我確信必須有更好的方法。
save方法在保存操作期間將線程鎖定在'object'的私有實例上,但這並不會停止正在更新的列表,因爲它是一個單獨的類,並且無法訪問該私有鎖。
所以,爲了解決這個問題,我所做的是向列表類添加一個'約改變'事件(不管它有什麼壞的特性),並且包含的類監聽這個事件,並鎖定與save方法在同一個私有鎖上,但不採取任何行動。這迫使線程等待,直到保存完成,然後允許更新列表,即使列表本身不知道它包含對象,或者它正在做什麼。
這裏的(嚴重簡化的)源:
public class ItemContainer
{
private ItemList _itemList = new ItemList();
private object _padlock = new object();
public ItemContainer()
{
_itemList.ItemAdded += StartTimedSave;
_itemList.ItemAdding += (sender, e) => { lock(_padlock) { } };
}
private StartTimedSave()
{
// starts or resets a half second timer to call Save();
}
private void Save()
{
lock(_padlock)
{
foreach (object obj in _itemList)
{
// save it.
}
}
}
}
public class ItemList
{
public event EventHandler<CancelEventArgs> ItemAdding;
public event EventHandler ItemAdded;
public List<object> _list;
public void Add(object obj)
{
if (ItemAdding.RaiseWithCancel(this)) // extension method
return;
_list.Add(obj);
ItemAdded.Raise(this); // another extension method
}
}
我不能逼真地具有列表保持對它的引用的包含對象,作爲列表是可以或可以不包含一個相當廣義類由這樣一個對象。
是一個空的lock { }
塊的事件處理程序真的要走這條路嗎?我對允許事件處理程序干擾提升它的對象的操作的想法感到不舒服,但我看不到更好的方法。
我想這個例子可能有點太簡化了;我再看看我的代碼,並且實際上存在的不僅僅是這一個可以在保存期間在外部修改的列表。我想我真正希望的是,有一種鎖定方式可以防止該進程中的任何其他線程運行,直到完成保存爲止,但我懷疑這是無法完成的。 – Flynn1179 2010-07-09 08:09:52