Параллельные задачи и блокировка локальных переменных - PullRequest
0 голосов
/ 30 мая 2018

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

В моей работе у меня есть что-то вроде этого примера:

public class Job
{
    private readonly IUserBLO _userBLO;
    private readonly IRequestBLO _requestBLO;
    private readonly object _lockerSheet;

    public Job()
    {
        _userBLO = Factory.CreateInstance("UserBLO");
        _requestBLO = Factory.CreateInstance("RequestBLO");
        _lockerSheet = new object();
    }

    public void ProcessJob(BinaryWriter binary)
    {
        using (ExcelPackage package = new ExcelPackage(binary))
        {
            var sheet = package.Workbook.Worksheet[1];

            var rows = Enumerable.Range(sheet.Dimensions.Start.Row, sheet.Dimensions.End.Row);

            Parallel.ForEach(rows, row =>
            {
                try
                {
                    var excelData = GetExcelData(sheet, row);

                    ValidadeData(excelData);

                    _requestBLO.OpenRequestByExcelData(excelData);
                }
                catch (Exception ex)
                {
                    LogError(ex);
                }
            });
        }
    }

    public List<string> GetExcelData(ExcelWorksheet sheet, int row)
    {
        var excelData = new List<string>();

        for (int i = sheet.Dimensions.Start.Column; i <= sheet.Dimensions.End.Column; i++)
        {
            lock (_lockerSheet)
            {
                var cellValue = sheet.Cells[row, i].Text;
            }

            excelData.Add(cellValue);
        }

        return excelData;
    }

    public void ValidadeData(List<string> excelData)
    {
        var userLogin = excelData.First();

        var user = _userBLO.FindByLogin(userLogin);

        if (user == null)
            throw new Exception("User not found!");
    }
}

Когда я кодировал, у меня были некоторые проблемы, которые, когда я пытался получить значение из листа в случайной позиции, иногда возвращалось пустымхотя эта позиция имела значение.После некоторого поиска в Google, я попытался использовать шкафчик в тот момент, когда я получал значение из листа, и, по-видимому, работал!

lock (_lockerSheet)
{
    var cellValue = sheet.Cells[row, i].Text;
}

После этой ситуации у меня возникло несколько вопросов:

  1. Каждая «локальная» переменная, которая будет параллельно использоваться в задачах, должна быть заблокирована, даже если эта переменная доступна только для чтения.Я прав?
  2. Если приведенный выше вопрос верен, нужно ли мне использовать блокиратор в переменных _userBLO и _requestBLO, которые являются интерфейсами, связанными с некоторыми конкретными методами?
  3. Если первыйвопрос ложный, мне просто нужно использовать шкафчик, если переменная получит какое-то значение в задаче?Когда мне действительно нужно использовать шкафчик?

PS: Извините за мой плохой английский!Бразильский здесь!:)

...