在C#中,当并行运行异步任务时,最后一个会一次又一次地运行

时间:2016-11-26 10:40:01

标签: c# asynchronous parallel-processing task

当从服务器读取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"]);
    }

1 个答案:

答案 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;