繁体   English   中英

在单独的线程上处理保存

[英]Handling a save on a separate thread

我有一个包含(除其他事项外)一系列项目的类,这些项目需要尽可能实际地保存到磁盘中。 为了做到这一点,无论何时进行任何更改,它都会使用计时器将保存到磁盘的时间延迟半秒,如果在此半秒内发生任何进一步的更改,则会延迟计时器。 换句话说,只要半秒内没有任何更改,它将保存到磁盘。

但是,我遇到了线程问题,可以在保存过程中修改列表。 我已经提出了一种修复它的方法,但是感觉有点像破解,而且我很确定必须有一个更好的方法。

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 { }块的事件处理程序真的是解决这个问题的方法吗? 我对允许事件处理程序干扰引发它的对象的操作的想法感到不舒服,但是我找不到更好的方法。

保存时,将列表复制到内存中并保存-这将减少数据暴露给其他线程中的更新。

为了确保线程安全,请让ItemList类创建并返回列表副本,并且ItemList类可以将内部列表锁定足够长的时间以进行复制:

public List<object> CreateListCopy()
{
    List<object> result = new List<object>();
    lock(_list)
    {
        foreach(object o in _list)
        {
            result.Add(o.Clone());
        }
    }

    return result;
}

然后,将CreateListCopy()的结果保存到保存线程中。

编辑:复制项目列表时,不要忘记确保您使用的是深层复制语义,因为您不想仅复制引用; 您需要完整,完全独立的数据副本。

这什么都不做:

锁(_padlock){}

块执行期间锁定保持-没有指向锁定空块的指示。

如果所有问题都与该私有锁对象有关,则只需为其公开获取即可。 确保任何修改或读取集合的东西都将其锁定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM