Переделка программы для использования многопоточности

Имеется программа Windows service, написанная на C#, которая периодически получает набор данных у стороннего web-cервиса, обрабатывает их и записывает в базу данных. Изначально не подразумевалась последовательная загрузка массивов данных. Сначала грузится один набор, потом следующий и т.д. Но со временем объём загружаемых данных и кол-во наборов увеличилось и возникла необходимость загружать их в параллельном режиме. Загрузка одного набора данных стала занимать более часа. Если говорить вкратце, то требуется запуск метода одного и того же класса с различными параметрами в многопоточном режиме. Каждый поток должен запускаться в изолированном режиме и не должен каким-либо образом влиять на одновременное выполнение других аналогичных потоков. Параллельно запускаемые потоки никак между собой не взаимодействуют. Т.е. необходимо чтобы каждый поток работал только со своими экземплярами данных и никак не мог испортить значения переменных, используемых другим потоком.

Грубо говоря есть некий класс DataMultiLoader, содержащий метод Load_and_Export

public class DataMultiLoader
{
                public DataMultiLoader(ServiceLogger p_svLogger)
                {
                    svLogger = p_svLogger;
                    cMTExporter = new Farelogix.MTExport.FQ_Exporter();
                }
            
                public void Load_and_Export(eProviders p_Provider, int p_nRRKey, RoutesLoadScheduler p_RScheduler)
                {   
                // здесь выполняется много работы с вызовом методов других классов, в том числе и статических
                    ...
                }
        
        }

    

Отдельная процедура LoadMultiThreading, которая вызывается по таймеру, должна запускать Load_and_Export из класса DataMultiLoader в рамках отдельного изолированного потока.

private void LoadMultiThreading(eBookingProviders p_Provider, int p_nRRKey) {

DataMultiLoader amdLoader = new DataMultiLoader(amdLogger);

...
Thread amdThread;
ThreadStart thStart;

thStart = delegate () { amdLoader.Load_and_Export(p_Provider, nSelectedRRKey, oRScheduler); };
amdThread = new System.Threading.Thread(thStart);
amdThread.Priority = ThreadPriority.AboveNormal;
amdThread.IsBackground = true;  
amdThread.Start();
...
}

Я просмотрел теоретические материалы по данной теме и выяснил, что в многопоточных приложениях существует проблема состязания за ресурсы, когда один поток портит данные другого.

Что надо добавить в существующий код, чтобы сделать его потоко безопасным?

Использование локальных блокировок данных с конструкциями типа

lock(lockObj) {
// синхронизируемые операторы
}

является неприемлемым из-за большого объёма существующего кода. По-хорошему здесь не нужна какая-либо синхронизация изменения данных, а нужна полная изолированность, как если бы процедура Load_and_Export запускалась в рамках отдельного процесса.

Можно ли достичь нужного результата если оформить класс DataMultiLoader следующим образом?

[Synchronization]
public class DataMultiLoader: ContextBoundObject
{
         ...
    public void Load_and_Export(eProviders p_Provider, int p_nRRKey, RoutesLoadScheduler p_RScheduler)
        {   
            ...
    }
}

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


Ответы (0 шт):