WCF- iClientMessageInspector-后方的错误本金
上下文
我有.NET Framework 4.6.1 WebAPI应用程序。该应用程序调用各种Web服务。因此,我已经实现了 iclientMessageInspector
以进行一些登录
WCF(SOAP)请求/答复。
但是
,在一段时间后,我意识到有些答复是在另一个校长下记录的,即校长A提出请求并收到答复,但响应却在校长B中记录下来。
以下是该实现的简化简约示例演示这个问题。
public class MyClientMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var correlationState = new CorrelationState
{
Guid = Guid.NewGuid()
};
// Principal A
Debug.WriteLine(Thread.CurrentPrincipal);
// Guid: 2abf9a7b-dac2-4c0d-b38d-1cdfb95405a7
Debug.WriteLine(correlationState.Guid);
return correlationState;
}
public void AfterReceiveReply(ref Message reply, object correlationStateObject)
{
var correlationState = (CorrelationState) correlationStateObject;
// Principal B - How come???
Debug.WriteLine(Thread.CurrentPrincipal);
// Guid: 2abf9a7b-dac2-4c0d-b38d-1cdfb95405a7 (matches Guid from request)
Debug.WriteLine(correlationState.Guid);
}
}
thread.currentprincipal
和 httpcontext.currentuser
仅在 global.asax.asax.cs
中设置在 application_postauthenticaterequest
。
该应用程序大量使用异步/等待范式,几乎所有异步调用(包括Web服务的呼叫)随后是 .configureawait(false)
。但是,我的理解是 thread.currentprincipal
是在线程之间流动的,无需使用 configureawait(false)
。这似乎是正确的,因为我的所有其他日志都是在正确的主体下制作的,即使是在之后发生的那些日志。
问题
是否有解释,为什么 thread.currentprincipal
eaterreceivereply 包含不同的主体?我知道如何解决这个问题 - 我可以在 beforesendrequest
和之后发送主体
coloreLation> correlationState object。但是在这样做之前,我需要理解为什么我的代码的行为与预期的不同,以及是否有比解决方案更好的解决方案。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您在使用螺纹池的应用程序上使用.configureawait(false)时,可以选择池中的任何线程以继续执行。其中一些线程可能与您的原始线程具有相同的上下文,而其他线程可能具有不同的上下文。一旦使用.configureawait(false),您就无法控制什么线程接管。
这里有一个更详细的描述:
上面的文章谈论使用.configureawait(false)。您曾经在呼叫堆栈中的任何位置拨打.phait()或。重要的是,只有当您的代码实际上在等待某件事时,才会发生这种情况。如果您的异步方法恰好具有他们需要继续的数据,他们将很乐意保留在其原始线程上,并且上下文变量将匹配。
同样,使用.configureawait(false)运行异步时,您可以从第一个线程发送到另一个线程,然后如果它是免费的,则返回到第一个线程,并且代码需要等待网络读取的内容。该线程池意味着您的线程数量有限,并且大多数涉及线程的操作实际上并没有旋转一个全新的螺纹。
一些进一步的阅读可能会有所帮助:
When you use .ConfigureAwait(false) on an application with a threadpool any of the threads in the pool might be chosen to continue execution. Some of those threads might have the same context as your originating thread, others might have different contexts. You have no control over what thread takes over once you use .ConfigureAwait(false).
There is a more detailed description of what's going on here: https://medium.com/rubrikkgroup/understanding-async-avoiding-deadlocks-e41f8f2c6f5d
The above article talks about using .Result and Task.Run, not .ConfigureAwait(false) however .ConfigureAwait(false) effectively does this behind the scenes anyway if you ever call a .wait() or .result on the call anywhere in your call stack. Importantly this only happens if your code is actually waiting for something. If your async methods happen to have the data they need to continue they will happily stay on their original thread and the context variables will match.
Also when running Async with .ConfigureAwait(false) you can be sent from your first thread to another thread, then back to your first thread if it's free and the code needed to wait for something like a network read. The threadpool means you have a limited number of threads that can be called on and most operations that involve threads don't actually spin up a completely new one.
Some further reading that might help:
https://devblogs.microsoft.com/dotnet/configureawait-faq/