Загрузка...

Потокобезопасные очереди. Идеальное решение для ****а

Тема в разделе C# создана пользователем RaysMorgan 8 янв 2017. 1200 просмотров

Загрузка...
  1. RaysMorgan
    RaysMorgan Автор темы 8 янв 2017 https://lolz.live/support-tickets/open 51 796 7 мар 2013
    Всем привет. Сегодня поговорим про потокобезопасные очереди (ConcurrentQueue).
    Потокобезопасные очереди - очереди, которые можно использовать в потоках и не переживать про то, что один объект из очереди может попасть в один и тот же поток.

    Рассмотрим создание объекта, здесь нет ничего не обычного по сравнению с обычной Queue, кроме того, что в параллельной очереди нельзя задать ее емкость (Capacity) в круглых скобках.
    Назовем объект как 'lines':

    Код

    ConcurrentQueue<string> lines= new ConcurrentQueue<string>();

    Конечно, внутри <> можно указать желаемый (например, int) тип данных (рекомендую указывать тип всегда)

    Также можно скопировать какой-нибудь лист или массив в эту очередь.
    Для этого в классе создадим объект без инициализации:
    Код
    ConcurrentQueue<string> lines;

    Затем в каком-нибудь методе, например startBtn_Click
    Код

    public void startBtn_Click(object sender, EventArgs e)
    {
    // тут куча кода, которая не интересна
    lines = new ConcurrentQueue<string>(myList);
    // myList - ваш лист, откуда нужно скопировать данные из листа в очередь
    }

    Ни в коем случае не пишите никогда что-то типо такого для копирования данных из одного объекта в другой:

    Код

    ConcurrentQueue<string> lines = new ConcurrentQueue<string>();
    ConcurrentQueue<string> newLines = new ConcurrentQueue<string>();
    lines.Enqueue("test");
    lines.Enqueue("for");
    lines.Enqueue("lolzteam.org");

    newLines = lines;

    Так вы не скопируете данные из lines в newLines, а просто сделаете очередь newLines ссылкой на lines.

    Правильно так:
    Код

    newLines = new ConcurrentQueue<string>(lines);


    Теперь рассмотрим выбор и добавление объектов в очередь. Как я писал уже ранее, такой тип очереди - потокобезопасен, поэтому не нужно использовать lock для добавления/выборки данных в очереди/из очереди.

    Для добавления данных в очередь используется тот же метод, что и в обычной очереди: Enqueue

    Код

    newLines.Enqueue("lolzteam.org guide");

    Так писать нельзя:
    Код

    lock (lockThis) {
    newLines.Enqueue("lolzteam.org guide");
    }


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

    Код

    string item;
    lines.TryDequeue(out item);

    Ещё лучше проверять очередь на наличие элементов, для этого используйте bool метод isEmpty, а потом проверять string item на наличие в ней символов:
    Код

    string item;
    if (!lines.IsEmpty) {
    lines.TryDequeue(out item);
    }
    if (string.IsNullOrEmpty(item) {
    // выходим из цикла или завершаем поток
    }

    Модификатор параметра out указывать обязательно! На сегодня всё! Если у вас остались вопросы, спрашивайте.
     
  2. iPro_inactive
    iPro_inactive 31 янв 2017 Заблокирован(а) 30 15 июн 2016
    бамп
    Код
    Queue mySafeQueue = Queue.Synchronized(myNotSafeQueue);
     
Top