简体   繁体   English

等待异步方法后的长任务

[英]Long task after await in an async method

While the following question is generally applicable to all usage of async/await in C#, it refers to Json.NET. 尽管以下问题通常适用于C#中的async / await的所有用法,但它引用的是Json.NET。 The JsonConvert.DeserializeObjectAsync() method has been marked as obsolete by the development team as it would be difficult to maintain and not of much use since most JSON files are small (Refer this ). JsonConvert.DeserializeObjectAsync()方法的特点是开发团队为过时的,因为大多数JSON文件很小(参见将难以维持,而不是多大用处这个 )。

I have some code following this structure: 我有一些遵循此结构的代码:

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));
}

Would option 1 or 2 in the code above be the better solution here? 上面代码中的选项1或2在这里是更好的解决方案吗?

Arguably this is primarily opinion-based. 可以说这主要是基于观点的。 But… 但…

Assuming the library authors are correct, your first option is better. 假设库作者是正确的,那么您的第一个选择会更好。 But not for the reason you think. 但这不是您想的原因。

When the await GetJsonStringFromRestEndpoint() completes, then assuming the GetCarAsync() method was called from a thread with a synchronization context, the call to DeserializeObject<CarObj>(json); await GetJsonStringFromRestEndpoint()完成时,假定从具有同步上下文的线程中调用了GetCarAsync()方法,则对DeserializeObject<CarObj>(json);的调用DeserializeObject<CarObj>(json); will happen on that same thread. 将在同一线程上发生。

The reason calling the method synchronously isn't a problem isn't because you're on a different thread (you're not), but rather because as the library authors point out, the input data isn't likely to be large enough for there to be any significant performance problem. 同步调用该方法不是问题的原因不是因为您在不同的线程上(不是),而是因为如库作者所指出的那样,输入数据可能不够大否则会出现严重的性能问题。 You can probably parse the entire JSON data and construct your CarObj value in less time than it takes to queue up the thread pool work item, context-switch to that thread, and then context-switch back. 您可能可以解析整个JSON数据并以比将线程池工作项排队,上下文切换到该线程然后上下文切换回去所花费的时间更少的时间来构造CarObj值。

In other words, don't use worker threads to perform computationally inexpensive work. 换句话说,不要使用辅助线程来执行计算上不昂贵的工作。

// At this point, we should already be on a separate thread since we have awaited a long running task. //至此,由于我们已经等待了长时间运行的任务,因此我们应该已经处于单独的线程中。

No, the caller thread is called back (resumed) instead. 不, 调用者线程将被调回(恢复)。

But - if this is not your intended behavior - I'd advice to add 但是-如果这不是您的预期行为-建议您添加

 .ConfigureAwait(false);

That would save some synchronization work and afterwards you'll reasonably expect to be in a thread pull thread. 这样可以节省一些同步工作,然后您可以合理地期望它处于线程拉线程中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM