【发布时间】:2015-08-09 18:22:42
【问题描述】:
我正在使用 async-await 方法创建一个应用程序。但是使用它们对我来说存在很大的问题。在阅读了几篇文章后,我仍然不知道将繁重的同步操作包装到异步方法的最佳方法是什么。
我有两个想法。哪个最好?
1) 当前实现。
private Task<List<UploadedTestModel>> ParseTestFiles(List<string> filesContent)
{
var tcs = new TaskCompletionSource<List<UploadedTestModel>>();
Task.Run(() =>
{
var resultList = new List<UploadedTestModel>();
foreach (var testBody in filesContent)
{
try
{
var currentCulture = Thread.CurrentThread.CurrentCulture;
var serializerSettings = new JsonSerializerSettings
{
Culture = currentCulture
};
var parsedData = JsonConvert.DeserializeObject<UploadedTestModel>(testBody, serializerSettings);
resultList.Add(parsedData);
}
catch(Exception exception)
{
tcs.SetException(exception);
}
}
tcs.SetResult(resultList);
});
return tcs.Task;
}
我正在使用 Task.Run 和 TaskCompletionSource
2) 仅使用没有 TaskCompletionSource 的 Task.Run
private Task<List<UploadedTestModel>> ParseTestFiles(List<string> filesContent)
{
return Task.Run(() =>
{
. . . .
return resultList;
});
}
【问题讨论】:
-
Task.Run 大约是您将获得的最好的 - 您不能通过仅以特殊方式调用它来使固有的同步操作真正异步。如果操作是 CPU 密集型的(或者只是包装了一些阻塞线程的东西),它需要在线程上运行。
-
据我所知,
foreach的主体本身可以以异步方式运行(resultList.Add除外)。即使在那之后,我也不确定JsonConvert.DeserializeObject是否真的从并行任务中受益。也许您应该使用信号量将并行计算限制在特定数量 - 比如 CPU 的数量?再一次,我不确定这个数字——你是在 x64 还是 x86 上,我不确定你可以从 .NET 的线程池机制中受益多少——这是底层的Taskrunner(调度程序)。 -
& 老实说,我只是盲目地信任
Tasks 的 .NET 底层机制,我做得很好。但是对于更繁重的事情,您最好使用 Akka.NET 之类的东西。 -
@Egorikas 请记住
async和await在 UI 应用程序中的行为有点不同 - 它们保留上下文。所以你必须使用明确的Task启动;然后awaitTask。 -
@KavehShahbazian 我明白了。谢谢你的解释
标签: c# asynchronous task-parallel-library