如何不使用状态对象将对象从一个线程传递到另一个线程

时间:2011-04-29 23:02:58

标签: c# asp.net multithreading .net-4.0 log4net

我有一个ASP.NET应用程序,它使用类库程序集中的组件来进行Web服务调用。该组件使用线程池或某种自制的线程解决方案来生成后台线程,在其中进行同步Web服务调用。

在ASP.NET应用程序中使用日志记录组件,以及组件从服务调用时生成的后台线程调用的辅助类。

在ASP.NET中,HttpModule创建日志记录上下文对象并将其存储在HttpContext.Current.Items集合中。当需要记录消息以便使用将记录的消息放入上下文的信息来装饰记录的消息时,ASP.NET应用程序和帮助程序类中使用的帮助程序类从HttpContext.Current.Items获取日志记录上下文对象。

当直接从ASP.NET调用辅助类时,HttpContext.Current可用。

当从组件创建的后台线程调用辅助类时,HttpContext.Current为null,因此在记录消息时没有可用的日志记录上下文;记录的消息没用。

我无法控制创建服务调用线程的组件。如果我这样做,我会安排将日志记录上下文对象复制并传递给子线程。

我的日志记录上下文对象不能是静态的,因为它会被并发的ASP.NET请求线程覆盖而且会很糟糕。

我的日志记录上下文对象(简单的int /字符串属性)的成员可以标记为ThreadStatic,这将起作用,我不再需要使用HttpContext.Current.Items了。

我真正需要的是使.NET运行时复制对象(或者甚至传递引用;要么会这样做)并使其自动用于子线程。

我想知道是否可以添加< system.threading>元素到web.config并指定一个帮助类来创建线程,就像你可以在%lt; system.net>中为Web请求做的那样;

我还想知道是否可以使用某些属性标记我的Logging Context对象,使其自动复制。

我查看了log4nets LogicalThreadContext,尝试了它,但它没有用。我认为这是为了跨进程或appdomain边界传递日志记录上下文信息。

log4net的LogicalThreadContext在幕后使用了什么机制?来自System.Runtime.Remoting的东西?现在已弃用吗?

我的环境是.NET 4,因此可能使用.NET 4中的线程并行扩展或增强功能,现在可以实现。

任何人都知道这是否可能?我开始想不到了。

  • 更新*

我必须做以下事情:

Task<IEnumerable<Account>> accountsTask = Task<IEnumerable<Account>>.Factory.StartNew
    (
        instrumentationContext =>
            {
                var parentContext = instrumentationContext as Site.Instrumentation.InstrumentationContext;
                if (Site.Instrumentation.InstrumentationContext.Current == null && parentContext != null)
                    Site.Instrumentation.InstrumentationContext.Current = parentContext;
                return GetAccounts();
            },
        Site.Instrumentation.InstrumentationContext.Current
    );

GetAccounts()方法调用另一个类,而另一个类依赖于Site.Instrumentation.InstrumentationContext.Current

问题是,我宁愿不必更改代码以显式传入并在子线程中设置此状态对象 - 我希望.NET Framework自动为我执行此操作,以便代码(上面)创造任务不是更明智的,也不必改变。

如果没有其他人提供替代方案,Jon会得到绿色标记,因为我认为这是我唯一的现实选择,尽管任务不是线程。

1 个答案:

答案 0 :(得分:1)

如果我理解正确你需要做的就是将一个对象传递给线程签名,那么参数化线程的启动是什么?

static void Main(string[] args)
    {
        object j = new object();
       Thread t = new Thread(()=>childThread(j));
       t.Start();
    }

    private static void childThread(object someObject)
    {
        // do work
    }