C# 锁定字典条目与ConcurrentDictionary

C# 锁定字典条目与ConcurrentDictionary,c#,dictionary,C#,Dictionary,我正在尝试以下工作:我得到一个降价文本,需要修改每个规则,f.e.#-->h1,**表示斜体等 这是一场比赛,表演是比赛的重点之一 因此,我的方法非常简单:我将行拆分,然后为每个规则创建字典,并为每个规则启动一个任务,这样它们就可以并行工作: private Dictionary<Rule, Dictionary<int, string>> SplitLinesByRule() { var result = new Dictionary&l

我正在尝试以下工作:我得到一个降价文本,需要修改每个规则,f.e.#-->h1,**表示斜体等

这是一场比赛,表演是比赛的重点之一

因此,我的方法非常简单:我将行拆分,然后为每个规则创建字典,并为每个规则启动一个任务,这样它们就可以并行工作:

    private Dictionary<Rule, Dictionary<int, string>> SplitLinesByRule()
    {
        var result = new Dictionary<Rule, Dictionary<int, string>>();
        Dictionary<int, string> tmpLines;

        tmpLines = _formattedLines.Where(f => string.IsNullOrEmpty(f.Value)).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Block, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.StartsWith("*")).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Enumeration, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.Count(ff => ff == '*') > 1).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Cursive, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.StartsExactlyWith("~~~~")).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Code, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.StartsExactlyWith("####")).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Headline4, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.Length >= 3 && f.Value.StartsExactlyWith("###")).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Headline3, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.Length >= 2 && f.Value.StartsExactlyWith("##")).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Headline2, tmpLines);

        tmpLines = _formattedLines.Where(f => f.Value.Length >= 1 && f.Value.StartsExactlyWith("#")).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.Headline1, tmpLines);

        tmpLines = _formattedLines.Except(result.SelectMany(f => f.Value)).ToDictionary(f => f.Key, f => f.Value);
        result.Add(Rule.None, tmpLines);

        return result;
    } 
我的问题是:一行可以有多个规则,因此我的第一种方法是使用ConcurrentDictionary并添加行,它无法更新到位置队列并单独处理它们:

    private void TryUpdate(KeyValuePair<int, string> line, string newValue)
    {
        bool ok = _formattedLines.TryUpdate(line.Key, newValue, line.Value);
        if (!ok) _poisonQueue.Add(line.Key, line.Value);
    }
private void TryUpdate(KeyValuePair行,字符串newValue)
{
bool ok=_formattedLines.TryUpdate(line.Key、newValue、line.Value);
如果(!ok)_.queue.Add(line.Key,line.Value);
}
我想这会管用的,但是性能不会那么好,而且检查每一行都变得非常复杂,这不管用,再次检查规则

另一种方法是创建一个普通字典,并基本上锁定它更新的行,因此可能会有多个行被更新,但只有同一行被更新一次(不适用于示例):

private void TryUpdate(KeyValuePair行,字符串newValue)
{
锁定(line.Key作为对象)
{ 
_formattedLines[line.Key]=newValue;
}
}
问题当然是,只有最后一条规则会被更新,所以我需要在这里做一些其他的事情


还有别的方法我没注意到吗?还有其他方法比单独处理每个规则更有效吗?

每个LINQ查询都必须解析整个文件,因此您可以检查每行
规则数
次,而您可以在大多数情况下取消许多检查。这有点低效。我认为您应该在文件的各个部分上进行并行化,而不是按照规则进行并行化。此外,如果您有一个条目,比如说,有很多h1转换要做,而实际上没有其他事情要做,那么您将有一个任务完成所有的工作,而其他任务将在短时间内完成。
lock(line.Key作为对象)
将无法正常工作。每次激活一个新的锁对象时,它都会导致整数装箱。您需要引用类型的实例才能与
lock
一起使用。当您试图锁定值类型表达式时,编译器会给您一个错误,这是有原因的。你可以定义一个新的引用类型,它只是一个包含int字段的键?什么奖?你要和我分享吗?不,彼得,这只是我动机的一个解释,这是一个非常小的比赛,我做这些事情是为了学习@帕特里塞加希德:另一种方法是什么?由于某些规则适用于多行f.E.列表,因此不可能仅在50条车道上分割车道并对其进行处理。米克斯:这只是一个想法,我基本上不知道ConcurrentDictionary对我有什么好处,除了说“不”
    private void TryUpdate(KeyValuePair<int, string> line, string newValue)
    {
        bool ok = _formattedLines.TryUpdate(line.Key, newValue, line.Value);
        if (!ok) _poisonQueue.Add(line.Key, line.Value);
    }
    private void TryUpdate(KeyValuePair<int, string> line, string newValue)
    {
        lock (line.Key as object)
        { 
            _formattedLines[line.Key] = newValue;
        }
    }