0

Здравствуйте! Есть 10 List, в которые поступают новые данные и которые надо обрабатывать. Есть входящие данные в количестве >1000/сек, которые поступаю c рандомной частотой. Придумал 2 способа их обрабатывать, подскажите минусы/плюсы или 3ий вариант.

1ый способ

class MyClass
{
    //list который хранит все string
    List<List<string>> ListString = new List<List<string>>();
    //переменная для блокировки доступа
    List<Object> ListLocker = new List<Object>();
    //List c отдельным thread для каждого List
    List<Thread> ListThread;

    //конструктор
    public MyClass()
    {
        //инициализируем List
        for(int i = 0; i < 10; i++)
        {
            ListLocker.Add(new Object());
            ListThread.Add(new Thread(InitThread));
        }
    }     

    //функция для инициализации Thread
    private void InitThread()
    {
    }

    //псевдофункция определяет принадлежность String к одному из List
    private int SearchIndex(string String)
    {
        for(int i = 0; i < ListString.Count; i++)
        {
            if(String.Contains(i.ToString()))
            {
                return i;
            }
        }
        return -1;
    }

    //фунция принимает обновления из вне
    public void OnUpdate(string String)
    {
        //получаем индекс
        int i = SearchIndex(String);
        if(i > -1)
        {
            //добавляем входящие данные в свой List
            lock(ListLocker[i])
            {
                ListString[i].Add(String);
            }

            if(!ListThread[i].IsAlive)
            {
                ListThread[i] = new Thread(new ParameterizedThreadStart(ReadList));
                ListThread[i].Start(i);
            }
        }
    }

    //функция обрабатывает данные
    private void ReadList(object incomeIndex)
    {
        //convert
        int index = (int)incomeIndex;

        int ListLenght = 0;
        lock(ListLocker[index])
        {
            //получаем кол-во строк
            ListLenght = ListString[index].Count;
        }
        for(int i = 0; i < ListLenght; i++)
        {
            //обрабатываем 0 строку...
            WorkWithString(ListString[index][0]);

            lock(ListLocker[index])
            {
                //удаляем 0 строку
                ListString[index].RemoveAt(0);
            }

            //проверяем появились еще данные в ListString, если да, не отпускаем поток, анализируем все новые строки
            if(i == ListLenght)
            {                    
                lock(ListLocker[index])
                {
                    //получаем новое кол-во
                    ListLenght = ListString[index].Count;
                    if(ListLenght > 0)
                    {
                        //запускаем цикл for снова
                        i = -1;
                    }
                }
            }
        }
    }

    private void WorkWithString(string String)
    {
        //work, work
    }
}

В этом способе минус в том, что очень много ресурсов уходит на создание потока. ListThread[i].Start(i);

2 способ основан на бесконечном цикле, но зато с одним Thread

class MyClass2
{
    //list который хранит все string
    List<List<string>> ListString = new List<List<string>>();
    //переменная для блокировки доступа
    List<Object> ListLocker = new List<Object>();
    //List c отдельным thread для каждого List
    Thread Thread;

    //конструктор
    public MyClass2()
    {
        //инициализируем List
        for(int i = 0; i < 10; i++)
        {
            ListLocker.Add(new Object());
            Thread = new Thread(new ThreadStart(InitThread));
        }
    }

    //функция для инициализации Thread
    private void InitThread()
    {
    }

    //псевдофункция определяет принадлежность String к одному из List
    private int SearchIndex(string String)
    {
        for(int i = 0; i < ListString.Count; i++)
        {
            if(String.Contains(i.ToString()))
            {
                return i;
            }
        }
        return -1;
    }

    //фунция принимает обновления из вне
    public void OnUpdate(string String)
    {
        //получаем индекс
        int i = SearchIndex(String);
        if(i > -1)
        {
            //добавялем входящие данные в свой List
            lock(ListLocker[i])
            {
                ListString[i].Add(String);
            }

            if(!Thread.IsAlive)
            {
                Thread = new Thread(new ThreadStart(ReadList));
                Thread.Start();
            }
        }
    }

    private void ReadList()
    {
        //прокручиваем все ListString
        for(int index = 0; index < ListString.Count; index++)
        {
            lock(ListLocker)
            {
                if(ListString[index].Count > 0)
                {
                    //прокручиваем все String
                    for(int i = 0; i < ListString[index].Count; i++)
                    {
                        //обрабатываем 0 строку...
                        WorkWithString(ListString[index][0]);

                        //удаляем 0 строку
                        ListString[index].RemoveAt(0);
                    }
                }
            }  

            //не отпускаем поток, зацикливая его бесконечно
            if(index == ListString.Count)
            {
                index = -1;
                Thread.Sleep(0);
            }
        }
    }

    private void WorkWithString(string String)
    {
        //work, work
    }
}

Большой минус второго способа, в том, что во время работы функции ReadList(), идет блокировка и новые данные будут висеть в очереди на запись.

Так же есть еще один вопрос, касательно запуска Thread:

Thread = new Thread(new ThreadStart(InitThread));

Как сделать это правильно? Если так не делать при запуске приложения ругается, что переменная не инициализирована, а инициализировать без указания функции, невозможно. Спасибо!

andreycha
  • 25,167
  • 4
  • 46
  • 82
K.Oleg
  • 339
  • 2
    Как-то у вас всё вручную. Думаю, вам сюда: http://ru.stackoverflow.com/q/428327/10105 – VladD Aug 12 '16 at 12:49
  • Спасибо за ссылку, буду изучать. Но если все-таки брать мой код, что Вы можете подсказать? – K.Oleg Aug 12 '16 at 13:32
  • Для вашего варианта я бы точно так же взял producer/consumer и не парился. – VladD Aug 12 '16 at 14:00
  • Разобрал пример по ссылке, конечно гораздо удобнее, но не так "прозрачно" для понимая. Единственное в чем у меня остался вопрос, это в строке q.CompleteAdding(); после этого, добавление в коллекцию не возможно. А у меня такая ситуация, что например раз в секунду должна добавляться запись и анализироваться, т.е каждый раз для одной записи создавать новую коллекцию? потому что как повторно открыть для записи коллекцию я не нашел. – K.Oleg Aug 12 '16 at 14:29
  • Ну, насчёт прозрачности тут вопрос привычки. В вашем случае, очевидно, не нужно вызывать CompleteAdding, если данные ещё будут приходить. Вызывайте лишь тогда, когда больше данных точно не будет. – VladD Aug 12 '16 at 15:33

0 Answers0