If the job method is asynchronous, it will run on a thread pool thread, so it is natural it has different
ManagedThreadId from the one the filter runs on. The main difference between
ThreadLocal is the former is bound to a logical call (which can span across multiple threads), while the latter is bound to a particular thread.
Why don't you just use job parameter to store tenant id? It would be displayed in Dashboard, and be easier to debug.
filterContext.SetJobParameter("TenantId", tenantId) in your filter to set parameter value. You may even do it once in
IClientFilter when the job is enqueued since the arguments won't change even if the job fails and being requeued, no need to do it every time in
PerformContext as a job argument and use
context.GetJobParameter<string>("TenantId") to get parameter value.