Web API - 使用 HttpRequestMessage id 设置每个线程?

Y.S*_*Y.S 4 .net c# multithreading task-parallel-library asp.net-web-api

我有一个用 C# 编码的 Web api。

Web API 使用与其他内部组件共享的功能。它依赖于单线程流并使用线程本地存储来存储对象和会话信息。请不要说这是好还是坏,这就是我必须面对的。

在 Web api 中,我使用 SendAsync 实现了自定义消息处理程序 (DelagatingHandler)

protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
Run Code Online (Sandbox Code Playgroud)

它基于 TPL,有时会切换线程,当发生这种情况时,我基于线程的功能会变得混乱,因为我丢失了线程上下文和分配给它的所有数据。

我的想法是唯一标识 HttpRequestMessage,我认为使用相关 id 应该足够了

var requestId = request.GetCorrelationId();
Run Code Online (Sandbox Code Playgroud)

但我想存储任务中分配的每个线程的 HttpRequestMessage 的相关 ID。

所以我的问题基本上是我是否可以识别在特定任务下分配的线程并为其分配 id?

Yuv*_*kov 5

对于与上下文相关的问题,您可以使用CallContext.LogicalSetDataand CallContext.LogicalGetData,它只是IDictionary<string, object>在上下文之间流动的一个,并且具有写时复制(浅复制)语义。

由于您的数据是不可变的(根据docs),您可以将相关 id 映射到线程管理的线程 id:

protected async override Task<HttpResponseMessage> SendAsync(
                         HttpRequestMessage request, 
                         CancellationToken cancellationToken)
{
    var correlationId = request.GetCorrelationId();
    var threadId = Thread.CurrentThread.ManagedThreadId;

    CallContext.LogicalSetData(correlationId.ToString(), threadId);
}
Run Code Online (Sandbox Code Playgroud)

稍后检索 if 以确保您处于“有效线程”上。

可以在此处async-await找到关于调用上下文的好读物。