C# глобальная переменная в рамках потока
От: cipher  
Дата: 04.01.07 11:18
Оценка:
Необходимо работать с базой данных из разных потоков. База данных MySql, подключаюсь через Connector.NET.Для каждого потока хочу создать своё подключение к базе данных (пишет в базу данных только один поток, остальные только читают), т.е. создаю объекты MySqlConnection для каждого потока. Обращение к базе данных идёт из разных функций, разных классов. Для этого я создал ряд статических функций. Для работы этих функций необходимо передавать соответствующие ссылки на объекты MySqlConnection. Передавать эти ссылки в качестве параметра неудобно из-за вложенности функций. Хотелось бы в рамках каждого потока в любом месте кода иметь доступ к объекту MySqlConnection данного потока, т.е. иметь глобальную переменную в рамках потока.
Как это сделать.
Re: C# глобальная переменная в рамках потока
От: _FRED_ Черногория
Дата: 04.01.07 11:27
Оценка: 4 (1) +2
Здравствуйте, cipher, Вы писали:

C>Необходимо работать с базой данных из разных потоков. База данных MySql, подключаюсь через Connector.NET.Для каждого потока хочу создать своё подключение к базе данных (пишет в базу данных только один поток, остальные только читают), т.е. создаю объекты MySqlConnection для каждого потока. Обращение к базе данных идёт из разных функций, разных классов. Для этого я создал ряд статических функций. Для работы этих функций необходимо передавать соответствующие ссылки на объекты MySqlConnection. Передавать эти ссылки в качестве параметра неудобно из-за вложенности функций. Хотелось бы в рамках каждого потока в любом месте кода иметь доступ к объекту MySqlConnection данного потока, т.е. иметь глобальную переменную в рамках потока.

C>Как это сделать.

ThreadStaticAttribute:
  class ConnectionHolder
  {
    [ThreadStatic]
    private static IDbConnection connection;

    public static IDbConnection Connection {
      get {
        if(connection == null) {
          connection = …;
        }//if

        return connection;
      }
    }
  }
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re: C# глобальная переменная в рамках потока
От: Oyster Украина https://github.com/devoyster
Дата: 04.01.07 11:35
Оценка:
Здравствуйте, cipher, Вы писали:

C>Как это сделать.


_FRED_ уже дал правильный ответ
Автор: _FRED_
Дата: 04.01.07
, но от себя добавлю, что для тех же целей ещё можно напрямую использовать методы GetData()/SetData() ( + AllocateDataSlot/AllocateNamedDataSlot/GetNamedDataSlot) у класса System.Threading.Thread. Прийдётся написать больше кода, но такое решение является более гибким.
Re[2]: C# глобальная переменная в рамках потока
От: _FRED_ Черногория
Дата: 04.01.07 14:57
Оценка: +1
Здравствуйте, Oyster, Вы писали:

C>>Как это сделать.


O>…для тех же целей ещё можно напрямую использовать методы GetData()/SetData() ( + AllocateDataSlot/AllocateNamedDataSlot/GetNamedDataSlot) у класса System.Threading.Thread. Прийдётся написать больше кода, но такое решение является более гибким.


А в чём гибкость? Минусы: отсутствие проверок со стороны компилятора на то, что данные в принципе есть и слабая типизация.
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Большое спасибо
От: cipher  
Дата: 04.01.07 15:19
Оценка:
Re[3]: C# глобальная переменная в рамках потока
От: Oyster Украина https://github.com/devoyster
Дата: 05.01.07 09:04
Оценка: 9 (2)
Здравствуйте, _FRED_, Вы писали:

_FR>А в чём гибкость? Минусы: отсутствие проверок со стороны компилятора на то, что данные в принципе есть и слабая типизация.


Плюсы — можно сделать сколько угодно слотов, т.е. полезно, если количество данных уровня потока, которые тебе надо будет хранить, известно только на этапе выполнения. Конечно, можно сделать List<object> или Dictionary<string, object> и пометить его [ThreadStatic], так что этот плюс сомнителен, пожалуй.

Второй плюс — если тебе вдруг захочется перейти с TLS на хранилище уровня Call Context-а, например. В случае с атрибутами прийдётся все их менять на [ContextStatic], в случае же с использованием GetData()/SetData() можно будет написать свою обёртку и абстрагироваться от собственно места хранилища (использовать CallContext, если понадобится). Мы как раз на такой ситуации обожглись, когда выяснили, что в ASP.NET 2.0 контекст одного реквеста может за время своей жизни сменить несколько потоков и пришлось избавляться от [ThreadStatic] (описано, например, тут: http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx).
Re[4]: C# глобальная переменная в рамках потока
От: _FRED_ Черногория
Дата: 05.01.07 10:08
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Второй плюс — если тебе вдруг захочется перейти с TLS на хранилище уровня Call Context-а, например. В случае с атрибутами прийдётся все их менять на [ContextStatic], в случае же с использованием GetData()/SetData() можно будет написать свою обёртку и абстрагироваться от собственно места хранилища (использовать CallContext, если понадобится). Мы как раз на такой ситуации обожглись, когда выяснили, что в ASP.NET 2.0 контекст одного реквеста может за время своей жизни сменить несколько потоков и пришлось избавляться от [ThreadStatic] (описано, например, тут: http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx).


Да, гхм, интересно, но не будет ли это "преждевременной оптимизацией"
Help will always be given at Hogwarts to those who ask for it.
Re[5]: C# глобальная переменная в рамках потока
От: Oyster Украина https://github.com/devoyster
Дата: 05.01.07 10:14
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Да, гхм, интересно, но не будет ли это "преждевременной оптимизацией"


А тут уж по ситуации надо смотреть. Конечно, в конкретной ситуации, описанной автором первого поста, [ThreadStatic] хватит. Я лишь описал, почему GetData()/SetData() может быть лучше.

Мы вот тоже думали, что [ThreadStatic] хватит навсегда... пока не столкнулись с этой проблемой в ASP.NET
Re[4]: C# глобальная переменная в рамках потока
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 05.01.07 19:55
Оценка: +1
Здравствуйте, Oyster, Вы писали:

O>Второй плюс — если тебе вдруг захочется перейти с TLS на хранилище уровня Call Context-а, например. В случае с атрибутами прийдётся все их менять на [ContextStatic], в случае же с использованием GetData()/SetData() можно будет написать свою обёртку и абстрагироваться от собственно места хранилища (использовать CallContext, если понадобится).


Так опять-таки проще будет использовать атрибуты ThreadStatic/ContextStatic, только внутри обертки — и переход сделать легко, и ручной работы не в пример меньше.
Respectfully,
Alexander Fedin.
Re: C# глобальная переменная в рамках потока
От: Vlad Volkov  
Дата: 05.01.07 20:41
Оценка:
Здравствуйте, cipher, Вы писали:

C>Необходимо работать с базой данных из разных потоков. База данных MySql, подключаюсь через Connector.NET.Для каждого потока хочу создать своё подключение к базе данных (пишет в базу данных только один поток, остальные только читают), т.е. создаю объекты MySqlConnection для каждого потока. Обращение к базе данных идёт из разных функций, разных классов. Для этого я создал ряд статических функций. Для работы этих функций необходимо передавать соответствующие ссылки на объекты MySqlConnection. Передавать эти ссылки в качестве параметра неудобно из-за вложенности функций. Хотелось бы в рамках каждого потока в любом месте кода иметь доступ к объекту MySqlConnection данного потока, т.е. иметь глобальную переменную в рамках потока.

C>Как это сделать.

Гм. Не знаю кто как, а вот лично я бы сделал проще — я бы избавился насколько это возможно от статических функций... Так ли нужны они ? Не проще ли сделать некий класс, экземпляр которого внутри себя будет содержать экземпляр подключения а также собственно сам рабочий поток с бизнес-логикой ?
Или, как вариант, сделать некий "пул соединений", глобальный для приложения и из рабочих потоков эти соединения дергать по необходимости ?
Или, (имхо лучший вариант) заюзать какую-нибудь ORM либу (да хотя бы тот же NHibernate) и наслаждаться (заодно и поддержка многих SQL серверов будет "почти автоматом", при правильном подходе конечно)
... << RSDN@Home 1.2.0 alpha rev. 668>>
Re[5]: C# глобальная переменная в рамках потока
От: Oyster Украина https://github.com/devoyster
Дата: 08.01.07 11:05
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

A>Так опять-таки проще будет использовать атрибуты ThreadStatic/ContextStatic, только внутри обертки — и переход сделать легко, и ручной работы не в пример меньше.


Ну это пока тебе не захочется применить "внизу" то, для чего атрибута нет Например, Call Context-а на самом деле недостаточно для решения описанной проблемы с ASP.NET — нам в итоге пришлось в зависимости от приложения (не-ASP.NET или ASP.NET) использовать или Call Context, или HttpContext.Current.Items (для которого атрибутов уже нет и который хоть и использует CallContext, но как-то по особому поддерживается рантаймом ASP.NET, в результате чего при использовании его проблемы полностью уходят).
Re[5]: C# глобальная переменная в рамках потока
От: Oyster Украина https://github.com/devoyster
Дата: 08.01.07 11:10
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

A>Так опять-таки проще будет использовать атрибуты ThreadStatic/ContextStatic, только внутри обертки — и переход сделать легко, и ручной работы не в пример меньше.


Кстати, вот замечательный кусок переписки в тему моего предыдущего сообщения
Автор: Oyster
Дата: 08.01.07
— в log4net используется тот же подход, что в итоге и у нас в приложении, потому что "HttpContext uses CallContext but it is not _just_ a wrapper":

http://www.mail-archive.com/log4net-dev@logging.apache.org/msg01242.html
Re[2]: C# глобальная переменная в рамках потока
От: Igor Trofimov  
Дата: 08.01.07 13:23
Оценка: 8 (1) +1
O>добавлю, что для тех же целей ещё можно напрямую использовать методы GetData()/SetData() ( + AllocateDataSlot/AllocateNamedDataSlot/GetNamedDataSlot) у класса System.Threading.Thread. Прийдётся написать больше кода, но такое решение является более гибким.

Как ни странно, ThreadStatic быстрее
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.