Удобная вставка данных в список с многопоточностью - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь оптимизировать небольшую программу.Итак, вот основная идея:

У меня есть массив нефильтрованных данных, и я хочу передать это функции, которая дважды вызовет другую функцию для фильтрации данных и вставки в новый список.Первый вызов будет принимать данные из исходного массива в диапазоне от 0 => половины длины массивов, а второй будет делать то же самое, но с диапазоном от половины до последнего элемента.Таким образом, я должен сделать одновременную вставку отфильтрованных данных в один и тот же список.После завершения вставки отфильтрованный список может быть передан остальной части программы.Вот код:

    static void Main(string[] 
        {
            // the unfiltered list
            int[] oldArray = new int[6] {1,2,3,4,5,6};
            // filtered list
            List<int> newList= new List<int>();
            // Functions is my static class
            Functions.Insert(newList, oldArray )
            Continue_Program_With_Filtered_List(newList);
            // remaining functions...
        }

А вот класс Function:

public static class Functions
{
    public static void Insert(List<int> newList, int[] oldArray)
    {
        new Thread(() =>
        {
            Inserter(newList, oldArray, true);
        }).Start();
        new Thread(() =>
        {
            Inserter(newList, oldArray, false);
        }).Start();

        // I need to wait the result here of both threads
        // and make sure that every item from oldArray has been filtered
        // before I proceed to the next function in Main()
    }

    public static void Inserter(List<int> newList, int[] oldArray, bool countUp)
    {
        bool filterIsValid = false;
        int length = oldArray.Length;
        int halflen = (int)Math.Floor((decimal)length / 2);
        if (countUp)
        {
            // from half length to 0
            for (int i = 0; i < halflen; i++)
            {
                // filtering conditions here to set value of filterIsValid
                if(filterIsValid)
                    newList.Add(oldArray[i]);
            }
        }
        else
        {
            // from half length to full length
            for (int i = halflen + 1; i < length; i++)
            {
                // filtering conditions here to set value of filterIsValid
                if(filterIsValid)
                    newList.Add(oldArray[i]);
            }
        }
    }
}

Итак, проблема в том, что я должен ждать Function.Insert (), чтобы завершить каждый поток и пройти черезкаждый элемент до newList передается следующей функции в Main ().

Я не знаю, как использовать Tasks или асинхронный метод для чего-то подобного.Кстати, это всего лишь набросок программы.Любая помощь?

1 Ответ

0 голосов
/ 17 декабря 2018

В вашем случае также можно использовать PLINQ .

static void Main(string[] args)
{
    // the unfiltered list
    int[] oldArray = new int[6] { 1, 2, 3, 4, 5, 6 };
    // filtered list
    List<int> newList = oldArray.AsParallel().Where(filter).ToList();
    // remaining functions...
}

Вы также можете использовать AsOrdered() для сохранения порядка


Чтобы вернуться к исходному вопросу, вот что вы можете сделать
Примечание: Решение с минимальными изменениями в исходном коде, независимо от того, есть ли другие возможные оптимизации или нет
Дополнительное примечание: Имейте в виду, что могут быть проблемы с параллелизмом, в зависимости от того, что еще вы делаете с аргументами, передаваемыми этой функции.

public static async Task Insert(List<int> newList, int[] oldArray)
{
    ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();
    var task1 = Task.Factory.StartNew(() =>
    {
        Inserter(concurrentBag, oldArray, true);
    });
    var task2 = Task.Factory.StartNew(() =>
    {
        Inserter(concurrentBag, oldArray, false);
    });
    await Task.WhenAll(task1, task2);
    newList.AddRange(concurrentBag);
}

public static void Inserter(ConcurrentBag<int> newList, int[] oldArray, bool countUp)
{
    //Same code
}

Редактировать: Ваш второй for-loop неверно, замените его на это или вы потеряете один предмет

for (int i = halflen; i < length; i++)
...