当从服务器读取xml时,我必须运行多个数据库插入,所以为了有效地执行它,我试图并行运行处理函数。
这很好用,但由于某种原因,最后一个任务一次又一次地运行,即使它不被多次调用(我在调试器中彻底检查过)。
有问题的代码:
static string sLast = "";
static string sReadElement = "";
static Dictionary<string, string> dctEvent;
...
static void Main(string[] args)
{
XmlReader xrReader = XmlReader.Create(GetDataStream(), new XmlReaderSettings() { DtdProcessing = DtdProcessing.Parse });
try
{
Dictionary<string, Task> dctEventTasks = new Dictionary<string, Task>();
while (xrReader.Read())
{
switch (xrReader.NodeType)
{
case XmlNodeType.Element:
switch (xrReader.Name)
{
case "event":
dctEvent = new Dictionary<string, string>();
break;
...
default:
sReadElement = xrReader.Name;
break;
}
break;
case XmlNodeType.Text:
...
break;
case XmlNodeType.EndElement:
switch (xrReader.Name)
{
...
case "event":
if (!dctEvent.ContainsKey(dctEvent["gamenumber"]))
{
Func<Task> func = async () => await HandleEvent(dctEvent, lstParticipants, lstPeriods);
dctEventTasks.Add(dctEvent["gamenumber"], Task.Run(func));
}
break;
}
break;
}
}
Log("Last: " + sLast);
Task.WhenAll(dctEventTasks.Values);
}
catch (Exception ex)
{
Log(ex.Message);
}
Console.ReadKey();
}
private static async Task HandleEvent(Dictionary<string, string> dctEvent, List<Dictionary<string, string>> lstParticipants, List<Dictionary<string, string>> lstPeriods)
{
...
Log("Finished handling event: " + dctEvent["gamenumber"]);
}
答案 0 :(得分:0)
我解决了。 问题是dctEvent,lstParticiapnts和lstPeriods是静态的,并且通过main while循环的每次运行共享。因此,在编辑集合时,对于并行运行的其他异步方法,结果会发生变化。 解决方案是克隆集合,如下所示:
case "event":
if (!dctEventTasks.ContainsKey(dctEvent["gamenumber"]))
{
var cdctEvent = dctEvent.ToDictionary(entry => entry.Key,
entry => entry.Value);
var clstParticipants = lstParticipants.ToList();
var clstPeriods = lstPeriods.ToList();
Func<Task> func = async () => await HandleEvent(cdctEvent, clstParticipants, clstPeriods);
dctEventTasks.Add(dctEvent["gamenumber"], Task.Run(func));
}
break;