c# - 如何正确调用 Parallel.ForEach 循环中的调用异步方法
问题描述
如何正确调用 Parallel.ForEach 循环中的调用异步方法。billDataService.SaveBillDetail 和 GetProfileDetails 都是异步方法。在 SaveBillDetail 中保存在 MongoDB 中的数据。
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 中调用和保存数据。但是 Parallel.ForEach 循环我无法使用 await 调用异步方法,并且在 mongo 中保存数据也不起作用。在 Parallel.ForEach 循环内部我避免使用 await 的调用方法的前面。
解决方案
您可以将代码更改为如下所示,然后等待所有任务完成。
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);
推荐阅读
- asp.net - 如何在asp.net中为sql数据源输入文本'<'和'>'
- java - docker 容器中的 Java 进程在 docker stop 后始终以状态 137 结束
- ios - 从 magento 2.0 REST Api 获取多个产品图像以用于购物车列表 - Swift 4
- javascript - 如果两个布尔值为真但也可以为空或不存在,则返回真
- java - ColumnHideCommand makes the table columns to disappear in NatTable, when all table elements are selected
- dart - 屏幕外列表图块处理
- android - 如何在管道中缓存库?
- android - 保存后不显示个人资料图像(它只显示空白屏幕)
- .net - 发生意外关闭时,有什么方法可以防止 service.exe 损坏
- ionic-framework - Ionic 3 启动项目耗时太长