Как передавать объект между кубиками "c# код"?

matsa

Client
Регистрация
18.11.2012
Сообщения
53
Благодарностей
2
Баллы
8
Задача такая. Есть БД Mysql, куда пишутся логи. Надо создать Mysql соединение в начале программы (или в общем коде), использовать его по ходу программы (в разных кубиках отправлять логи, не открывая новое соединение, а используя первоначальное), ну и в конце программы последним действием его закрыть. Т е главная задача - не создавать каждый раз новые подключения при добавлении строчки в таблицу, а использовать одно.
 

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 860
Благодарностей
2 573
Баллы
113
В первом кубике: project.Context["connect"] = ...
Во втором кубике: var connect = project.Context["connect"];
Или var connect = (тут класс объекта для приведения типа) project.Context["connect"];
 
  • Спасибо
Реакции: matsa и samsonnn

matsa

Client
Регистрация
18.11.2012
Сообщения
53
Благодарностей
2
Баллы
8
Большое спасибо за помощь! В целом, буду использовать ваше решение. Но на всякий случай, приведу своё "творение"

В общем коде размещаем такой класс

C#:
namespace ZennoLab.OwnCode
{
    /// <summary>
    /// A simple class of the common code
    /// </summary>
    public class Log
    {
        public string message = "Привет";
        public int rnd = 123;
        
        public int Hi()
        {
            return rnd;
        }
        
        
        private static Log _instance;

        private Log() { Random zrnd = new Random(); rnd = zrnd.Next(30, 100); }
    
        public static Log Instance
        {
            get
            {
                if (_instance == null)
                {
                    
                    _instance = new Log();
                    
                }
                return _instance;
            }
        }
        
    };
    
}
В кубиках используем project.SendInfoToLog($"{Log.Instance.Hi()}");

Как думаете, это решение подойдёт? Не будет ли проблем в многопотоке?
 

Alex91

Известная личность
Read only
Регистрация
15.08.2024
Сообщения
880
Благодарностей
251
Баллы
63
Большое спасибо за помощь! В целом, буду использовать ваше решение. Но на всякий случай, приведу своё "творение"

В общем коде размещаем такой класс

C#:
namespace ZennoLab.OwnCode
{
    /// <summary>
    /// A simple class of the common code
    /// </summary>
    public class Log
    {
        public string message = "Привет";
        public int rnd = 123;
       
        public int Hi()
        {
            return rnd;
        }
       
       
        private static Log _instance;

        private Log() { Random zrnd = new Random(); rnd = zrnd.Next(30, 100); }
   
        public static Log Instance
        {
            get
            {
                if (_instance == null)
                {
                   
                    _instance = new Log();
                   
                }
                return _instance;
            }
        }
       
    };
   
}
В кубиках используем project.SendInfoToLog($"{Log.Instance.Hi()}");

Как думаете, это решение подойдёт? Не будет ли проблем в многопотоке?
А ты спроси у ИИ, раз закрались сомнения...

Он много что написал, сам почитаешь, вот краткая выдержка.

Итог
Да, текущий код не потокобезопасен.

Проблемы:

Возможны несколько экземпляров Log из-за гонки в Instance.

Random может давать одинаковые числа.

Публичные поля уязвимы к гонкам данных.

Как исправить:

Использовать lock или Lazy<T> для Singleton.

Переработать Random.

Защитить публичные поля или сделать их неизменяемыми.

Если Singleton должен быть потокобезопасным, лучше сразу использовать Lazy<T> — это самый надежный способ.
 

matsa

Client
Регистрация
18.11.2012
Сообщения
53
Благодарностей
2
Баллы
8
Да, тут согласен...ИИ много знает про c#, но про zennoposter - не так много .... по идее же, каждый инстанс в зеннопостере существует не зависимо друг от друга, им вообще должно быть побоку что там в другом инстансе происходит ...

но в любом случае, буду использовать то, что уже проверено опытом других пользователей, экспериментировать не буду =))
 

Alex91

Известная личность
Read only
Регистрация
15.08.2024
Сообщения
880
Благодарностей
251
Баллы
63
Да, тут согласен...ИИ много знает про c#, но про zennoposter - не так много .... по идее же, каждый инстанс в зеннопостере существует не зависимо друг от друга, им вообще должно быть побоку что там в другом инстансе происходит ...

но в любом случае, буду использовать то, что уже проверено опытом других пользователей, экспериментировать не буду =))
Это абсолютное заблуждение...
Общий код, с префиксами Статик , существует одновременно для всех потоков шаблона с одним именем.
И принципы работы c# абсолютно такие же как , как и в визуалке для контейнера Мэйн... Отличие только в том , что общий контейнер в зенно, это имя шаблона, а порождаемые потоки зенкой, это дочерние процессы этого контейнера.
 

matsa

Client
Регистрация
18.11.2012
Сообщения
53
Благодарностей
2
Баллы
8
Это абсолютное заблуждение...
Общий код, с префиксами Статик , существует одновременно для всех потоков шаблона с одним именем.
И принципы работы c# абсолютно такие же как , как и в визуалке для контейнера Мэйн... Отличие только в том , что общий контейнер в зенно, это имя шаблона, а порождаемые потоки зенкой, это дочерние процессы этого контейнера.
Большое спасибо! картина становится яснее =))

А можете ещё уточнить такой момент.
В многопотоке же по факту каждый поток использует одни и те же данные для подключения к БД, как на деле ведут себя открытые соединения с БД в разных потоках? Они как то пересекаются между собой? Я тут спрашиваю не про локи таблиц, а именно про подключения с БД.

Каждое подключение по одним и тем же данным авторизации с Mysql это всё разные подключения? Или одно? Могут ли они как то конфликтовать? (при условии разумного использования блокировок таблиц)
 

matsa

Client
Регистрация
18.11.2012
Сообщения
53
Благодарностей
2
Баллы
8
Хотя, что это я, ИИ всё знает =)))
Вы совершенно правы, что в многопоточной среде C# несколько потоков могут использовать одну и ту же строку подключения к базе данных (например, MySQL). Вот что происходит в этом случае и как это влияет на соединения с базой данных:


1. Каждое MySqlConnection – это отдельное подключение:


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


То есть:


  • new MySqlConnection(connectionString) не устанавливает соединение. Он просто создает объект MySqlConnection, который содержит информацию о том, как подключиться.
  • connection.Open() устанавливает физическое соединение с базой данных. Каждый вызов Open() (если соединение еще не открыто) устанавливает новое соединение.

2. Независимость соединений:


Каждое соединение, установленное разными потоками, является независимым от других. Они не “пересекаются” напрямую на уровне TCP/IP соединения. Каждый поток будет иметь свое собственное соединение с сервером MySQL.


3. Разные подключения, но один пользователь:


Несмотря на то, что это разные соединения, все они будут аутентифицированы под одним и тем же пользователем MySQL (в вашем примере, user). Права доступа и ограничения, установленные для этого пользователя, будут применяться ко всем соединениям.


4. Потенциальные конфликты:


Хотя соединения независимы, ошибки могут возникать из-за конфликтов на уровне базы данных:


  • Блокировки: Если один поток заблокировал таблицу (например, выполнив LOCK TABLES), другие потоки, пытающиеся получить доступ к той же таблице, будут ждать, пока блокировка не будет снята. Это самая распространенная причина конфликтов в многопоточной среде.
  • Deadlocks (взаимные блокировки): Если два потока заблокировали разные ресурсы и каждый ждет, пока другой освободит свой ресурс, возникает взаимная блокировка. MySQL может автоматически разрешать взаимные блокировки, выбирая один из потоков в качестве “жертвы” и откатывая его транзакцию.
  • Ограничения на количество соединений: У сервера MySQL есть ограничение на максимальное количество одновременных соединений. Если приложение создаст слишком много потоков, каждый из которых установит соединение, можно превысить этот лимит, и новые соединения будут отклонены. Это часто проявляется в виде исключения Too many connections.
  • Исчерпание ресурсов сервера: Большое количество одновременных соединений может привести к исчерпанию ресурсов сервера MySQL (например, памяти, CPU), что замедлит его работу.

5. Что рекомендуется делать:


  • Connection Pooling (пул соединений): Используйте Connection Pooling (который включен по умолчанию в MySqlConnector или MySql.Data). Connection Pooling позволяет повторно использовать существующие соединения вместо создания новых при каждом запросе. Это значительно снижает нагрузку на сервер MySQL и повышает производительность приложения. Пул соединений автоматически управляет соединениями, выдавая их потокам по мере необходимости и возвращая их в пул после использования.
  • Управляйте блокировками: Тщательно проектируйте свою схему блокировок, чтобы минимизировать время, в течение которого ресурсы заблокированы. Используйте наименьший возможный уровень блокировки (например, блокируйте только необходимые строки, а не всю таблицу). Избегайте длительных транзакций.
  • Транзакции: Используйте транзакции для обеспечения атомарности операций (ACID properties). Убедитесь, что транзакции не остаются открытыми слишком долго, чтобы не удерживать блокировки.
  • Асинхронные операции: Рассмотрите возможность использования асинхронных операций (например, async/await) для работы с базой данных. Это позволит вашему приложению оставаться отзывчивым, даже если операции с базой данных занимают много времени.
  • Мониторинг: Мониторьте количество активных соединений, время выполнения запросов и другие метрики производительности MySQL, чтобы выявлять и устранять проблемы.
  • Ограничьте количество потоков: Не создавайте слишком много потоков, которые одновременно работают с базой данных. Количество потоков должно быть разумным и соответствовать возможностям сервера MySQL.
  • Используйте правильные индексы: Убедитесь, что у вас есть индексы для часто используемых запросов. Это значительно ускорит выполнение запросов и уменьшит нагрузку на сервер.
  • Автоматическое закрытие соединений: Всегда закрывайте соединения, когда они больше не нужны. Используйте блоки using, чтобы гарантировать, что соединения будут закрыты, даже если возникнет исключение:
    using (MySqlConnection connection = new MySqlConnection(connectionString))
    {
    connection.Open();
    // ... работа с базой данных ...
    } // Соединение автоматически закрывается здесь




  • csharp

Пример с Connection Pooling (не требуется явная настройка, включен по умолчанию):



string connectionString = "Server=localhost;Database=zenno;Uid=user;Pwd=123123;";

// Поток 1
Thread t1 = new Thread(() =>
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
// ... выполнить запрос ...
Console.WriteLine($"Поток {Thread.CurrentThread.ManagedThreadId}: Выполнил запрос");
} // Соединение возвращается в пул
});

// Поток 2
Thread t2 = new Thread(() =>
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
// ... выполнить запрос ...
Console.WriteLine($"Поток {Thread.CurrentThread.ManagedThreadId}: Выполнил запрос");
} // Соединение возвращается в пул
});

t1.Start();
t2.Start();
t1.Join();
t2.Join();

csharp
В заключение:


В многопоточной среде C# каждый поток, использующий MySqlConnection и Open(), устанавливает отдельное физическое соединение с сервером MySQL. Хотя эти соединения независимы, важно учитывать потенциальные конфликты, связанные с блокировками, ограничениями на количество соединений и исчерпанием ресурсов сервера. Использование Connection Pooling, правильное управление блокировками, транзакциями и мониторинг производительности помогут вам избежать этих проблем и обеспечить эффективную и надежную работу вашего приложения.
 

Alex91

Известная личность
Read only
Регистрация
15.08.2024
Сообщения
880
Благодарностей
251
Баллы
63
Ну да... Но если заюзать всеми любимый Статик, то картина немного изменится :-)
 

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)