等待异步方法后的长任务

时间:2017-02-27 17:54:14

标签: c# json.net async-await

虽然以下问题通常适用于C#中async / await的所有用法,但它指的是Json.NET。 JsonConvert.DeserializeObjectAsync()方法已被开发团队标记为过时,因为它很难维护而且没有多大用处,因为大多数JSON文件很小(参考this)。

我有一些遵循这种结构的代码:

public async Task<CarObj> GetCarAsync()
{
    string json = await GetJsonStringFromRestEndpoint();
    // At this point, we should already be on a separate thread since we have awaited a long running task.

    // 1 - Running this relatively long task on this thread should be fine since we're already on a new thread than the caller.
    CarObj obj = JsonConvert.DeserializeObject<CarObj>(json);

    // 2 - Would this better for some reason?
    CarObj obj2 = await Task.Run(() => JsonConvert.DeserializeObject<CarObj>(json));
}

上面的代码中的选项1或2是否是更好的解决方案?

2 个答案:

答案 0 :(得分:3)

可以说这主要是基于意见的。但...

假设图书馆作者是正确的,你的第一个选择是更好。但不是你想的原因。

await GetJsonStringFromRestEndpoint()完成时,假设从具有同步上下文的线程调用GetCarAsync()方法,对DeserializeObject<CarObj>(json);的调用将在同一个线程上发生。

同步调用该方法的原因并不是问题,因为您处于不同的线程(您不是),而是因为正如图书馆作者所指出的那样,输入数据可能不足以存在任何重大性能问题。您可以解析整个JSON数据,并在比将线程池工作项,上下文切换到该线程,然后上下文切换回来所花费的时间更短的时间内构造CarObj值。

换句话说,不要使用工作线程来执行计算成本低廉的工作。

答案 1 :(得分:0)

  

//此时,我们应该已经在一个单独的线程上,因为我们已经等待了一个长时间运行的任务。

不,调用者线程被回调(恢复)。

但是 - 如果这你的预期行为 - 我建议添加

 .ConfigureAwait(false);

这可以节省一些同步工作,之后你会合理地期望在一个线程拉线程中。