Как правильно организовать многопоточность?

341
17 марта 2017, 23:22

cellsData - массив данных (List), который нужно записать в .xslx файл по средствам OpenXML, так как данных достаточно много, решили разбить запись в worksheet с помощью потоков.
Метод WriteCellInTable производит запись части sheetData в worksheet.

В одну и туже ячейку таблицы данные могут записываться несколько раз, важно что-бы в ячейке остались самые последние данные, а при работе с двумя и более потоками, при записи в одну и туже ячейку, возникает накладка и в ячейке могут остаться неактуальные данные. Как этого избежать и имеет ли место такое решение в принципе?

        int prCount = Environment.ProcessorCount;
        Thread[] threads = new Thread[prCount - 1];
        int part = cellsData.Count / prCount;
        int begin = 0, thrNum = 0;
        for (int i = 0; i < prCount; i++)
        {
            if (i == prCount - 1)
            {
                part = cellsData.Count - begin;
                WriteCellInTable(new Object[] { (Object)begin, (Object)part, (Object)sheetData }); //В текущем потоке
                break;
            }
            threads[thrNum] = new Thread(WriteCellInTable);
            threads[thrNum].Start(new Object[] { (Object)begin, (Object)part, (Object)sheetData }); //Новый поток
            begin += part;
            thrNum++;
        }
        Columns columns = new Columns();
        InsertColumnWidth(columns);
        MergeCells mergeCells = new MergeCells();
        SetMergeCell(mergeCells);
        for (int i = 0; i < thrNum; i++)
            threads[i].Join();
        worksheet.Append(new SheetFormatProperties() { DefaultRowHeight = 15D, DyDescent = 0.25D });
Answer 1

Если метод WriteCellInTable обращается одновременно из разных потоков к одному и тому же объекту без всякой синхронизации - это неправильно. Результаты измерения производительности такого кода не должны учитываться. Подробнее о синхронизации можно прочитать в данной статье

Но допустим, вы переделываете код, заключив содержимое WriteCellInTable в конструкцию lock. Тогда конфликты исчезнут, но цель увеличения производительности не будет достигнута. Дело в том, что выигрыш в производительности путем использования многопоточности можно получить только если потоки не конкурируют за общие ресурсы: обращаясь к разделяемому ресурсу, потоки будут проводить много времени в ожидании освобождения ресурса, и в итоге толку нет.

Чтобы действительно улучшить производительность, вы должны сделать, чтобы каждый поток оперировал только своим ограниченным множеством ячеек (например, один поток на один лист). Тогда можно ожидать какого-то улучшения производительности.

READ ALSO
Извлечение SingleNode

Извлечение SingleNode

Имеется xml:

228
Оптимизация кода создания потоков c#

Оптимизация кода создания потоков c#

Доброго времени суток, стоит задача : вызвать метод n раз использовав при этом m потоков (нужно, чтоб одновременно)Я тут набросал код

271
Renci.SshNet - ошибка

Renci.SshNet - ошибка

Код: using RenciSshNet; using Renci

369
Жизненный цикл приложений WinForms

Жизненный цикл приложений WinForms

Не знаю тонкостей технической реализации виртуальных машин под Java и C#, но знаю, что для приложений под Android выделяют понятие "жизненный цикл...

304