这个问题是关于以 async/await 或 Task.Run() 方式处理第三方同步文件读取方法(ChoXmlReader)。我有一个传入路径名列表,我用 .AsParallel 处理它们以使用更多线程。但是当 ChoXmlReader 执行同步工作时,线程可能会全部阻塞并等待。
我尝试使用以下表达式将 UxActionsPathReadOne 转换为 _Async,但我的应用程序似乎挂起。我认为这可能与混合任务并行 .AsParallel、惰性求值 LINQ .Select() 和 UxActionsPathReadOneAsync 的异步版本有关。我确定我有一个 .ToList() 来强制执行 LINQ 评估,但这没有帮助。在我在 VStudio 中运行的一次调试中,返回的 nestedActions 列表中充满了诸如“等待评估”之类的项目。
谁能解释为什么代码挂起并且不评估读取的 xml 文件?将复杂的 AsParallel.Select(asyncMethod).ToList() 拆分成多个语句有帮助吗?如果是这样,为什么?
我想我在理解中遗漏了一些东西,但我不知道它是什么。
更新: 我将代码恢复到同步工作状态,退出 VStudio,在 ChoXmlReader 调用上使用 async/await 从下往上重新修改所有代码,并修复(添加 await,修改方法接口)VStudio 中的所有错误。正如预期的那样,一切正常。
我重新检查了下面的代码,以确保它与我现在在 VStudio 中的工作代码相匹配。所以,我的原始异步代码可以正常工作,但我不知道为什么它会挂起并且没有工作足够长的时间来促使人们努力发布这个问题。
总之,这已经不是问题了。最好删除它。
这里是调用者中语句的同步/异步版本:
// this synchronous statement works fine
var nestedActions = paths.AsParallel().Select(UxActionsPathReadOne).ToList();
// this async statement fails, hangs, or doesn't evaluate something.
var nestedActions = paths.AsParallel().Select(UxActionsPathReadOneAsync).ToList();
这里是低级 xml 文件阅读器中语句的同步/异步版本。
// this original synchronous statement works fine
// this third party method reads the xml file and returns a list of items
var xmlItems = new ChoXmlReader<ActionItem>(path).ToList();
// this async version causes the problems mentioned above
var xmlItems = await Task.Run(() => new ChoXmlReader<ActionItem>(path).ToList());
这是工作正常的完整同步代码。
// The input to this calling method is a list of 20-50 pathnames to xml files to read
public static bool
ActionsPathsReadParallel(List<string> paths, out List<ActionItem> items) {
items = new List<ActionItem>();
// individual file read operations can return empty structures on read failures
var nestedActions = paths.AsParallel().Select(UxActionsPathReadOne).ToList();
// fail if there were failed read operations (or empty option files)
var empties = nestedActions.Where(x => x.Count == 0);
if (empties.Any()) return false;
// flatten the list of found xml items and return it
items = nestedActions.AsParallel().SelectMany(x => x).ToList();
return true;
}
// this method reads one XML file that could contain 50-100 xml items of 10 fields each
// It uses the ChoXmlReader, which is not named Async
public static List<ActionItem>
UxActionsPathReadOne(string path) {
var actionItems = new List<ActionItem>();
// this third-party method reads the xml file and returns a list of items
var xmlItems = new ChoXmlReader<ActionItem>(path).ToList();
xmlItems.AsParallel().ForAll(x => x.XmlPath = path);
xmlItems.AsParallel().ForAll(x => x.Spoken = x.Spoken.Trim().ToLower());
// more code that inspects, converts, and processes the xmlItems
return xmlItems;
}
请参阅原始问题中的更新。发布的代码确实工作正常。