我试图完成以下工作:我得到一个降价文本,需要改变每个规则,例如: # - > 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;
}
其次是:
Task[] tasks = new Task[]
{
Task.Factory.StartNew(() =>
{
HandleBlocks(lineChunks.First(f => f.Key == Rule.Block).Value);
}),
Task.Factory.StartNew(() =>
{
HandleCode(lineChunks.First(f => f.Key == Rule.Code).Value);
}),
Task.Factory.StartNew(() =>
{
HandleCursive(lineChunks.First(f => f.Key == Rule.Cursive).Value);
}),
Task.Factory.StartNew(() =>
{
HandleEnumeration(lineChunks.First(f => f.Key == Rule.Enumeration).Value);
}),
Task.Factory.StartNew(() =>
{
HandleH1(lineChunks.First(f => f.Key == Rule.Headline1).Value);
}),
Task.Factory.StartNew(() =>
{
HandleH2(lineChunks.First(f => f.Key == Rule.Headline2).Value);
}),
Task.Factory.StartNew(() =>
{
HandleH3(lineChunks.First(f => f.Key == Rule.Headline3).Value);
}),
Task.Factory.StartNew(() =>
{
HandleH4(lineChunks.First(f => f.Key == Rule.Headline4).Value);
}),
Task.Factory.StartNew(() =>
{
HandleNoneRule(lineChunks.First(f => f.Key == Rule.None).Value);
})
};
Task.WaitAll(tasks);
我的问题是:一行可以有多个规则,所以我的第一个方法是ConcurrentDictionary并添加Lines,它们无法更新到posion队列并单独处理它们:
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);
}
我想这会起作用,但是性能不会那么好,而且检查每条线路都会变得非常复杂,这对于规则来说也是行不通的。
另一种方法是创建一个普通的Dictionary并基本上锁定它更新的行,这样可能会有多行被更新,但只有同一行一次(不是工作示例):
private void TryUpdate(KeyValuePair<int, string> line, string newValue)
{
lock (line.Key as object)
{
_formattedLines[line.Key] = newValue;
}
}
问题当然是,只有最后一条规则会更新,所以我需要在这里做其他事情。
还有其他方法我没有照顾吗?是否有另一种方法比试图为自己处理每条规则更有效率?