c# HttpContext.Current.Items 在生成线程中为空

c# HttpContext.Current.Items is null in spawn thread

我有以下api方法:

public IHttpActionResult Post(LogModel value)
{
        try
        {
            IDictionary items = HttpContext.Current.Items;
            Thread thread = new Thread(() => LogSQL.LogDetail(items, value));
            thread.Start();

            return Ok();
        }
        catch (Exception ex)
        {
            ...
        }
    }

在命中控制器之前,会调用验证和授权代码,这会在HttpContext.Current.Items中保存一些数据。

对于新威胁,HttpContext.Current.Items 为空,因此我从父线程传递项目数据以在子线程中设置该威胁。

public static void LogDetail(IDictionary items, LogModel log)
    {
        var keys = (from System.Collections.DictionaryEntry dict in items
                           let key = dict.Key.ToString()
                           select key).ToList();

        foreach (var key in keys)
        {
            HttpContext.Current.Items[key] = items[key];
        }

... }

但这不起作用。 HttpContext.Current.Items 为空且只读,因此我无法以任何方式设置它。

我可以将 'items' 参数全部传递给新线程中需要数据的任何地方,但尽量避免它。

关于如何解决这个问题有什么想法吗?我可以使用任何穿线技巧吗?

HttpContext.Current绑定到处理HTTP请求的线程。如果您生成一个新线程,它将没有关联的上下文。

I can pass the 'items' parm all over to whatever needs the data in the new thread, but trying to avoid it.

这是正确的做法。从当前上下文中提取您需要的任何内容并将其传递给您的线程。

请注意,在处理 HTTP 请求时生成线程有些危险,因为

  • 与请求无关的线程中的未处理异常将关闭进程。
  • 如果您 运行 您的站点位于 Web Farm 中,您最终可能会得到应用程序的多个实例,它们都会同时尝试 运行 同一任务。
  • 您的站点 运行 所在的 AppDomain 可能会因多种原因而关闭,并随之关闭您的后台任务。

(Source,以及有关该主题的好读物,包括更好的方法)