c#需要在LOCK范围内引发事件

时间:2010-11-22 13:17:20

标签: c# events locking

我有一个文件处理程序类,它使用锁将xdoument移动到缓存中。  Psuedo代码:

public FetchDocument() {
    var xdoc = Cache[_Key1];
    if (xdoc == null) {
        lock(_lockobject) {
            // in case prev.thread has done upload will currth read waiting
            xdoc = Cache[_Key1];

            if (xdoc == null) {
               .... Code to grab from file and add to catch - works great.....
            }
        }
    }
    xdoc = Cache[_Key1];

}

现在我想公开和在文件加载之后但在缓存之前触发的事件以及在事件上有中止标志的事件。

问题是我如何只触发当前(未锁定)线程的事件?

可能会锁定另一个线程,等待此线程清除锁定代码

由于

马丁

2 个答案:

答案 0 :(得分:0)

所有事件都由当前线程处理,如果您的任何事件处理程序尝试调用UI线程或采取其他锁定,则会出现问题。
在这种情况下,Monitor.TryEnter可能会对这些事件处理程序有所帮​​助。

但最好的办法是将你的锁分成两个锁,一个在事件之前,一个在事件之后。

答案 1 :(得分:0)

如果我理解正确,您希望允许调用者中止缓存文档。你可以通过将Func传递给你的FetchDocument方法来实现这一点,例如:

public XDocument FetchDocument(FUnc<XDocument, bool> cacheNewDocument) {
    var xdoc;        
    lock(_lockobject) {
        // in case prev.thread has done upload will currth read waiting
        xdoc = Cache[_Key1];

        if (xdoc == null) {
           xdoc = .... Code to grab from file and add to catch - works great.....

           if (cacheNewDocument(xdoc)){
               Cache.Add(_Key1, xdoc)
           }
           else{
               return xdoc;
           }
        }
    }

    return xdoc;
}

这样,在将文档添加到缓存之前,您的代码可以使用相关数据调用Func,并且调用者可以返回true \ false以获取您的中止语义。

这比使用事件要简单得多,并强制执行“我如何仅为当前(未锁定)线程触发事件”语义。

另一方面,虽然您的原始代码是伪代码,但您正在访问锁外的Cache对象。即使这些未锁定的操作是读操作,集合也可能在锁内变异,因此您可能会得到不可预测的结果。缓存中的所有操作都应该在锁中完成。