在异步code赔率使用[ThreadStatic] [英] Is the use of [ThreadStatic] at odds with asynchronous code?

查看:202
本文介绍了在异步code赔率使用[ThreadStatic]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有建立在ASP.NET之上,并且code大量使用访问的 HttpContext.Current.User (包装为 Client.User ),这我相当肯定在内部使用 [ThreadStatic] 给你该环境作用域。

We have a fairly large existing code base for various webservices built on top of ASP.NET and that code makes heavy use of accessing HttpContext.Current.User (wrapped as Client.User) which I'm fairly sure internally uses [ThreadStatic] to give you that ambient scoping.

我目前正在研究是否有可能,我们开始异步/的await 的形式多采用异步code,但我有一个硬时间发现使用 [ThreadStatic] 如何适应这一点。拆除的依赖 [ThreadStatic] 是不是真的有可能由于其大量使用。

I'm currently looking into if it's possible that we start to use more asynchronous code in the form of async/await but I'm having a hard time finding how the use of [ThreadStatic] fits into this. Removing the reliance on [ThreadStatic] isn't really possible due to its heavy use.

这是我的理解是,当一个等待被击中时,code的执行停在那里,调用立即返回并继续设置为继续在执行时,异步code的回报。同时,原来的线程是自由地可用于其他内容,例如,以处理另一个请求。到目前为止,我理解这一点。

It's my understanding that when an await is hit, the execution of the code stops there, the call immediately returns and that a continuation is set up to continue the execution when the asynchronous code returns. Meanwhile, the original thread is free to be used for something else, for example to handle another request. So far my understanding of it.

我真的不能找到一个的明确的答案为否 HttpContext.Current.User 保证是同前和之后的await

What I can't really find a definitive answer to is whether or not HttpContext.Current.User is guaranteed to be the same before and after the await.

所以基本上:

HttpContext.Current.User = new MyPrincipal();
var user = HttpContext.Current.User;

await Task.Delay(30000);

// Meanwhile, while we wait for that lots of other requests are being handled, 
// possibly by this thread.

Debug.Assert(object.ReferenceEquals(HttpContext.Current.User, user));

Debug.Assert的保证成功?

如果另一个请求是由同一个线程中 Task.Delay 被挂起,这个请求就已经设置了不同的 HttpContext.Current处理。用户,所以是previous状态莫名其妙地存储和恢复的时候继续叫?

If another request was handled by the same thread as the Task.Delay was pending, that request will have set a different HttpContext.Current.User, so is that previous state somehow stored and restored when the continuation is called?

我可以想像发生的是幕后的 [ThreadStatic] 状态保持为某种线程本身的字典,并且当一个线程返回线程池上返回等待该字典保持一个安全的地方,并设置返回到当它执行延续线程(或上的的线索后,我不知道这是否是必然连的处理的延续相同的线程),可能与对接一个令人鼓舞的拍拍和走出去得到'时间的男孩!,但最后一部分也许只是是我的想象。

What I can imagine happening is that behind the scenes the [ThreadStatic] state is kept as some sort of dictionary on the thread itself and that when a thread returns to the thread pool after returning on that await that dictionary is kept safe somewhere and set back onto the thread when it executes the continuation (or on a thread, I'm not sure if it's necessarily even the same thread that handles the continuation), probably with an encouraging pat on the butt and a "go get 'em boy!", but that last part might just be my imagination.

那是有点不爽?

更新:我试图把一个小的测试,尝试这一点。到目前为止,似乎工作,并断言没有失败的出数百个请求的。如果测试是有道理的任何人都可以验证?

UPDATE: I've tried to put together a small test that attempts this. So far it seems to work and the assertion hasn't failed for any out of hundreds of requests. Can anyone verify if the test makes sense?

https://gist.github.com/anonymous/72d0d6f5ac04babab7b6

推荐答案

异步 / 伺机是线程无关,这意味着他们有一个约定,可以在多个不同的线程系统内工作。

async/await are thread-agnostic, meaning that they have a convention that can work within multiple different threading systems.

在一般 ThreadStatic 不会异步 / 正常工作等待,除了微不足道的情况下,如UI上下文,其中等待将恢复UI线程。对于ASP.NET, ThreadStatic 不兼容异步

In general ThreadStatic will not work correctly in async/await, except for trivial cases such as UI contexts where await will resume on the UI thread. For ASP.NET, ThreadStatic is not compatible with async.

然而, HttpContext.Current 是一个特例。 ASP.NET定义了一个请求上下文(通过重新分配给 SynchronizationContext.Current AspNetSynchronizationContext 实例psented $ P $ )。默认情况下,等待 ING一个任务将捕获此同步上下文并用它来恢复方法。当恢复的方法,它的可能会在不同的线程的,但它具有相同的请求上下文(包括 HttpContext.Current 以及其他的东西,如文化,安全)。

However, HttpContext.Current is a special case. ASP.NET defines a "request context" (represented by an AspNetSynchronizationContext instance assigned to SynchronizationContext.Current). By default, awaiting a task will capture this synchronization context and use it to resume the method. When the method resumes, it may be on a different thread, but it will have the same request context (including HttpContext.Current as well as other things such as culture and security).

因此​​, HttpContext.Current 是preserved,但任何自己的 ThreadStatic 值都没有。

So, HttpContext.Current is preserved, but any of your own ThreadStatic values are not.

我描述了如何等待的SynchronizationContext 工作在我的 异步介绍。如果您想了解更多详细信息,请参阅我的 的SynchronizationContext MSDN文章(特别是在异步CTP最后一节)

I describe how await works with SynchronizationContext in my async intro. If you want more details, check out my SynchronizationContext MSDN article (particularly the last section on the async CTP).

这篇关于在异步code赔率使用[ThreadStatic]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆