Как передать объект из одного потока в другой без использования объекта состояния - PullRequest
0 голосов
/ 30 апреля 2011

У меня есть приложение ASP.NET, которое использует компонент в сборке библиотеки классов для выполнения вызовов веб-службы. Компонент использует пул потоков или какое-либо решение для создания потоков, созданное в домашних условиях, для создания фоновых потоков, в которых выполняются синхронные вызовы веб-службы.

Компонент ведения журнала используется в приложении ASP.NET и вспомогательными классами, которые компонент вызывает из фоновых потоков, порождаемых при вызовах службы.

В ASP.NET HttpModule создает объект контекста ведения журнала и сохраняет его в коллекции HttpContext.Current.Items. Вспомогательные классы, используемые в приложении ASP.NET и во вспомогательных классах, извлекают объект контекста ведения журнала из HttpContext.Current.Items, когда необходимо зарегистрировать сообщение, чтобы украсить зарегистрированное сообщение информацией, которая помещает зарегистрированное сообщение в контекст .

Когда вспомогательные классы вызываются напрямую из ASP.NET, доступен HttpContext.Current.

Когда вспомогательные классы вызываются из фоновых потоков, созданных компонентом, HttpContext.Current имеет значение null, и поэтому для них нет доступного контекста протоколирования при регистрации сообщений; зарегистрированные сообщения бесполезны.

У меня нет контроля над компонентом, который создает потоки для выполнения сервисных вызовов. Если бы я это сделал, я бы организовал копирование и передачу объекта контекста в дочерний поток.

Мой объект контекста ведения журнала не может быть статическим, поскольку он будет перезаписан параллельными потоками запросов ASP.NET, и это будет плохо.

Члены моего объекта контекста протоколирования (простые свойства int / string) могут быть помечены ThreadStatic, что будет работать, и мне больше не нужно будет использовать HttpContext.Current.Items.

Что мне действительно нужно, так это чтобы рабочая среда .NET скопировала объект (или даже передала ссылку; либо сделал бы), и автоматически сделала его доступным для дочерних потоков.

Мне было интересно, смогу ли я добавить элемент в web.config и назначить вспомогательный класс для создания потоков, как вы можете сделать для веб-запросов в% lt; system.net>

Мне также было интересно, могу ли я пометить свой объект контекста ведения журнала каким-либо атрибутом, который вызывает его автоматическое копирование.

Я заглянул в log4nets LogicalThreadContext, попробовал, но это не сработало. Я думаю, что это для передачи информации о контексте регистрации через процессы или границы домена приложения.

Какой механизм LogicalThreadContext log4net использует за кулисами? Что-то из 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 сделал это для меня автоматически, чтобы код (см. Выше) это создает задачу, которая не мудрее и не должна быть изменена.

Если никто не вносит свой вклад в альтернативы, Джон получает зеленую галочку, поскольку я решил, что это был мой единственный реалистичный выбор, хотя задачи были не потоками.

1 Ответ

1 голос
/ 02 мая 2011

Если я вас правильно понимаю, все, что вам нужно сделать, это передать объект в подпись потока, так что не так с параметризованным запуском потока ??

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
    }
...