Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的暂定锁?_C#_.net_.net 3.5_Locking - Fatal编程技术网

C#中的暂定锁?

C#中的暂定锁?,c#,.net,.net-3.5,locking,C#,.net,.net 3.5,Locking,假设我希望允许并行执行某些代码,但需要其他代码等待所有这些操作完成 让我们设想一下,除了锁,还有一个软锁: public static class MySimpleCache { private static readonly SynchronizedCollection<KeyValuePair<string, string>> Collection = new SynchronizedCollection<KeyValuePair<string,

假设我希望允许并行执行某些代码,但需要其他代码等待所有这些操作完成

让我们设想一下,除了
,还有一个
软锁

public static class MySimpleCache
{
    private static readonly SynchronizedCollection<KeyValuePair<string, string>> Collection = new SynchronizedCollection<KeyValuePair<string, string>>();

    public static string Get(string key, Func<string> getter)
    {
        // Allow parallel enumerations here,
        // but force modifications to the collections to wait. 
        softlock(Collection.SyncRoot)
        {
            if (Collection.Any(kvp => kvp.Key == key))
            {
                return Collection.First(kvp => kvp.Key == key).Value;
            }
        }

        var data = getter();

        // Wait for previous soft-locks before modifying the collection and let subsequent softlocks wait
        lock (Collection.SyncRoot)
        {
            Collection.Add(new KeyValuePair<string, string>(key, data));
        }
        return data;
    }
}
公共静态类MySimpleCache
{
私有静态只读SynchronizedCollection=新SynchronizedCollection();
公共静态字符串Get(字符串键,Func getter)
{
//此处允许并行枚举,
//但强制对集合的修改等待。
软锁(Collection.SyncRoot)
{
if(Collection.Any(kvp=>kvp.Key==Key))
{
返回Collection.First(kvp=>kvp.Key==Key).Value;
}
}
var data=getter();
//在修改集合之前等待以前的软锁,并让后续的软锁等待
锁(Collection.SyncRoot)
{
添加(新的KeyValuePair(key,data));
}
返回数据;
}
}
C#/.NET中是否有任何设计模式或语言/框架特性可以直接可靠地实现这一点,还是必须从头开始实现这一点


我目前只对.NET 3.5感兴趣,我主要对概念问题感兴趣,而不是对其他可能解决这个例子本身的集合感兴趣。

在这种情况下,你可以使用,它将允许多个读卡器,直到有人想写,然后它会阻止所有读卡器,只允许一个写卡器通过

public static class MySimpleCache
{
    private static readonly SynchronizedCollection<KeyValuePair<string, string>> Collection = new SynchronizedCollection<KeyValuePair<string, string>>();
    private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();

    public static string Get(string key, Func<string> getter)
    {
        //This allows multiple readers to run concurrently.
        Lock.EnterReadLock();
        try
        {
            var result = Collection.FirstOrDefault(kvp => kvp.Key == key);
            if (!Object.Equals(result, default(KeyValuePair<string, string>)))
            {
                return result.Value;
            }
        }
        finally
        {
            Lock.ExitReadLock();
        }


        var data = getter();

        //This blocks all future EnterReadLock(), once all finish it allows the function to continue
        Lock.EnterWriteLock();
        try
        {
            Collection.Add(new KeyValuePair<string, string>(key, data));
            return data;
        }
        finally
        {
            Lock.ExitWriteLock();
        }
    }
}

p.S.您在评论中提到,该值可能为null,因此
FirstOrDefault()
将不起作用。在这种情况下,使用扩展方法生成
TryFirst()
函数

public static class ExtensionMethods
{
    public static bool TryFirst<T>(this IEnumerable<T> @this, Func<T, bool> predicate, out T result)
    {
        foreach (var item in @this)
        {
            if (predicate(item))
            {
                result = item;
                return true;
            }
        }
        result = default(T);
        return false;
    }
}

//Used like
Lock.EnterReadLock();
try
{
    KeyValuePair<string, string> result;
    bool found = Collection.TryFirst(kvp => kvp.Key == key, out result);
    if (found)
    {
        return result.Value;
    }
}
finally
{
    Lock.ExitReadLock();
}
公共静态类扩展方法
{
公共静态bool TryFirst(this IEnumerable@this,Func谓词,out T result)
{
foreach(@this中的变量项)
{
if(谓语(项))
{
结果=项目;
返回true;
}
}
结果=默认值(T);
返回false;
}
}
//像
Lock.EnterReadLock();
尝试
{
键值对结果;
boolfound=Collection.TryFirst(kvp=>kvp.Key==Key,out结果);
如果(找到)
{
返回结果值;
}
}
最后
{
Lock.exitradelock();
}

在这种情况下,您可以使用,它将允许多个读卡器,直到有人想写,然后它将阻止所有读卡器,并且只允许一个写入器通过

public static class MySimpleCache
{
    private static readonly SynchronizedCollection<KeyValuePair<string, string>> Collection = new SynchronizedCollection<KeyValuePair<string, string>>();
    private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();

    public static string Get(string key, Func<string> getter)
    {
        //This allows multiple readers to run concurrently.
        Lock.EnterReadLock();
        try
        {
            var result = Collection.FirstOrDefault(kvp => kvp.Key == key);
            if (!Object.Equals(result, default(KeyValuePair<string, string>)))
            {
                return result.Value;
            }
        }
        finally
        {
            Lock.ExitReadLock();
        }


        var data = getter();

        //This blocks all future EnterReadLock(), once all finish it allows the function to continue
        Lock.EnterWriteLock();
        try
        {
            Collection.Add(new KeyValuePair<string, string>(key, data));
            return data;
        }
        finally
        {
            Lock.ExitWriteLock();
        }
    }
}

p.S.您在评论中提到,该值可能为null,因此
FirstOrDefault()
将不起作用。在这种情况下,使用扩展方法生成
TryFirst()
函数

public static class ExtensionMethods
{
    public static bool TryFirst<T>(this IEnumerable<T> @this, Func<T, bool> predicate, out T result)
    {
        foreach (var item in @this)
        {
            if (predicate(item))
            {
                result = item;
                return true;
            }
        }
        result = default(T);
        return false;
    }
}

//Used like
Lock.EnterReadLock();
try
{
    KeyValuePair<string, string> result;
    bool found = Collection.TryFirst(kvp => kvp.Key == key, out result);
    if (found)
    {
        return result.Value;
    }
}
finally
{
    Lock.ExitReadLock();
}
公共静态类扩展方法
{
公共静态bool TryFirst(this IEnumerable@this,Func谓词,out T result)
{
foreach(@this中的变量项)
{
if(谓语(项))
{
结果=项目;
返回true;
}
}
结果=默认值(T);
返回false;
}
}
//像
Lock.EnterReadLock();
尝试
{
键值对结果;
boolfound=Collection.TryFirst(kvp=>kvp.Key==Key,out结果);
如果(找到)
{
返回结果值;
}
}
最后
{
Lock.exitradelock();
}

听起来像是您需要的,它可以从读卡器锁开始,升级到写器锁。您的查找效率稍低,您可以枚举两次,您可以使用
var result=Collection.FirstOrDefault(kvp=>kvp.Key==Key);如果(result!=default(KeyValuePair)){return result.Value;}
并且只查找一次。@MatthewWatson谢谢,这看起来非常合适,我将使用它。哎呀!=不起作用,但我正在编写一个答案(使用ReaderWriterLockSlim),该答案也将有一个固定版本。@ScottChamberlain,但我通常无法区分集合是否不包含该值,或者它包含的值是否为null。听起来您需要一个从读卡器锁开始的答案,您的查找效率稍低,枚举两次,可以使用
var result=Collection.FirstOrDefault(kvp=>kvp.Key==Key);如果(result!=default(KeyValuePair)){return result.Value;}
并且只查找一次。@MatthewWatson谢谢,这看起来非常合适,我将使用它。哎呀!=不起作用,但我正在编写一个答案(使用ReaderWriterLockSlim),该答案也将有一个固定版本。@ScottChamberlain,不过我通常无法区分集合是否不包含该值,或者它包含的值是否为null。