【问题标题】:how to call Call Async Methods in Parallel.ForEach loop properly [duplicate]如何正确调用 Parallel.ForEach 循环中的调用异步方法[重复]
【发布时间】:2020-09-09 00:59:21
【问题描述】:

如何正确调用 Parallel.ForEach 循环中的调用异步方法。billDataService.SaveBillDetail 和 GetProfileDetails 都是异步方法。数据保存在 MongoDB 中的 SaveBillDetail 中。

public async Task ConvertXMLFileToJSON()
        {
            try
            {

                if (Directory.Exists(_appSettings.DocumentsStorage))
                {
                    int i = 1; //Test
                    bool exists = Directory.GetFiles(_appSettings.DocumentsStorage).Any(x => x.Equals(Path.Combine(_appSettings.DocumentsStorage, "Ready.txt"), StringComparison.OrdinalIgnoreCase)); //Need to check
                    if (exists)
                    {
                      Parallel.ForEach(System.IO.Directory.GetFiles(_appSettings.DocumentsStorage, "*.xml"), (currentFile) =>
                        {
                            try
                            {
                                XElement root = XElement.Load(currentFile); // or .Parse(string);
                                //Removing CDATA property from XElement.
                                XElement items = XElement.Parse(root.ToString().Replace("<![CDATA", "").Replace("]]>", "").Replace("[", ""));
                                //Removing XML_INFO Tag from XElement.
                                items.Elements("XML_INFO").Remove();
                                XmlDocument xmlDoc = new XmlDocument();
                                using (XmlReader xmlReader = items.CreateReader())
                                {
                                    xmlDoc.Load(xmlReader);
                                }

                                var json = JsonConvert.SerializeXmlNode(xmlDoc);
                                billDetails obj = JsonConvert.DeserializeObject<billDetails>(json);
                                BillDetails billDetails = new BillDetails();
                                billDetails.AccountNumber = obj.BILL_INFO.BILL_RUN.ACCT_INFO.ACCT_CODE;
                                billDetails.MobileNumber = obj.BILL_INFO.BILL_RUN.ACCT_INFO.PRINCIPAL_NO.STR_PRINCIPAL_NO;
                                billDetails.BillDate = DateTime.ParseExact(obj.BILL_INFO.BILL_RUN.BILL_PROP.TO_DATE, "dd/MM/yyyy", CultureInfo.InvariantCulture);
                                billDetails.DueAmount = obj.BILL_INFO.BILL_RUN.ACCT_INFO.ACCT_BALANCE_TRACE.TOTAL_DUE;
                                billDetails.CustomerName = obj.BILL_INFO.BILL_RUN.CUST_INFO.CUST_NAME.FULL_NAME;
                                billDetails.InvoiceId = obj.BILL_INFO.BILL_RUN.BILL_PROP.INVOICE_ID;
                                billDetails.DueDate = DateTime.ParseExact(obj.BILL_INFO.BILL_RUN.BILL_PROP.DUE_DATE, "yyyyMMdd hh:mm:ss", CultureInfo.InvariantCulture);
                                billDetails.RepositoryName = "postpaid";
                                billDetails.BillRun = obj.BILL_INFO.BILL_RUN; //tempObj2.BILL_INFO.ToString().Remove(0, 1);
                                billDetails.ObjectId = Guid.NewGuid().ToString();
                                if (billDetails != null)
                                {
                                    BillDataService billDataService = new BillDataService(_dbConfig);
                                    Console.WriteLine("SaveBillDetail");
                                    if (billDataService.SaveBillDetail(billDetails) != null)
                                    {
                                        Console.WriteLine("SaveBillDetail done");
                                        GetProfileDetails(billDetails);
                                        _logger?.LogInformation(i++ + "  File Success");
                                        Console.WriteLine(i++ + "  File Success");
                                        // File.Delete(file);  //Delete File 
                                    }
                                }

                            }
                            catch (Exception ex)
                            {
                                _logger?.LogError(ex, "Error");
                            }
                            finally { }
                        });
                    }
                }
            }

            catch (Exception ex)
            {
                _logger?.LogError(ex, "Error");
            }
            finally
            {

            }
        }


public async Task GetProfileDetails(BillDetails billDetails)
        {
            try
            {
                ProfileService profileService = new ProfileService(_dbConfig);
                var searchFilter = new SearchFilter
                {
                    Filters = new List<Filter>()
                };

                if (!string.IsNullOrEmpty(billDetails.AccountNumber))
                {
                    searchFilter.Filters.Add(new Filter() { PropertyName = "AccountNumber", Operator = Operator.Equals, Value = billDetails.AccountNumber, CaseSensitive = true });
                }

                if (searchFilter != null)
                {
                    Profile profile = await profileService.GetProfiles(searchFilter);
                    if (profile != null)
                    {
                        await SendMailNotification(profile, billDetails);
                    }
                    else
                    {
                        _logger?.LogError("Profile Info not found");

                    }
                }
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "Error");
                throw;
            }
            finally { }
        }


正常的每个循环我可以在 MongoDB.but Parallel.ForEach 循环中调用和保存数据调用方法前面的await。

【问题讨论】:

    标签: c# .net mongodb asp.net-core


    【解决方案1】:

    您可以将代码更改为如下所示,然后等待所有任务完成。

    var fileTasks = System.IO.Directory.GetFiles(_appSettings.DocumentsStorage, "*.xml").Select(async currentFile =>
                            {
                                try
                                {
                                    XElement root = XElement.Load(currentFile); // or .Parse(string);
                                    // rest o your code here
                                    if (billDetails != null)
                                    {
                                        if (billDataService.SaveBillDetail(billDetails) != null)
                                        {
                                            Console.WriteLine("SaveBillDetail done");
                                            await GetProfileDetails(billDetails);
                                        }
                                    }
                                 }
                              catch(exception ex) { //log exeption }
                           });
    
    await Task.WhenAll(fileTasks);
    

    【讨论】:

    • 它正在工作,但没有变化。每个循环的性能与正常情况相比是相同的。
    猜你喜欢
    • 1970-01-01
    • 2017-03-06
    • 2014-10-09
    • 2012-09-10
    • 2022-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多