简体   繁体   English

在C#中,当并行运行异步任务时,最后一个将永远运行一次

[英]In C#, when running async tasks in parallel, the last one runs again and again forever

When reading an xml from the server, I have to run multiple database inserts, so to do it efficiently I'm trying to run the handling functions in parallel. 从服务器读取xml时,我必须运行多个数据库插入,因此为了有效地做到这一点,我试图并行运行处理函数。

This works nicely but for some reason the last task runs again and again forever even though it is not called more than once (I checked it thoroughly in the debugger). 这可以很好地工作,但是由于某种原因,最后一个任务会一次又一次地永远运行,即使它的调用不止一次(我在调试器中彻底检查了它)。

The code in question: 有问题的代码:

    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"]);
    }

I solved it. 我解决了 The problem was that dctEvent, lstParticiapnts and lstPeriods were static and shared through every run of the main while loop. 问题在于dctEvent,lstParticiapnts和lstPeriods是静态的,并且在主while循环的每次运行中都共享。 So when the collections were edited the result would change for other async methods running parallel. 因此,当编辑集合时,对于并行运行的其他异步方法,结果将发生变化。 The solution was to clone the collections like so: 解决的办法是像这样克隆集合:

                            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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM