Parallel.Invoke Не работает должным образом в C# - PullRequest
0 голосов
/ 27 мая 2020

Я вызываю пакет SSIS из моего кода C#. Пакет обрабатывает один за другим файл и удаляет его из определенной папки.

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

Я написал эту функцию для получения прогресса:

private void fileIteration(string folderPath)
{
    int initialFileCount, fileCount, processCount;        
    initialFileCount = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly).Length;
    this.Invoke(new MethodInvoker(delegate (){ progressBar1.Value = initialFileCount;}));

    if (initialFileCount > 0)
    {
        fileCount = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly).Length;

        while (fileCount != 0)
        {
            // Thread.Sleep(2000);
            fileCount = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly).Length;
            processCount = initialFileCount - fileCount;
            this.Invoke(new MethodInvoker(delegate () { progressBar1.Increment(processCount); }));
            initialFileCount = initialFileCount + processCount;
        }
    }
}

Поскольку обе задачи должны выполняться параллельно, я вызываю вот так:

  Parallel.Invoke(

            () => fileIteration(folderPath),// for prgressbar
            () => results = package.Execute()); // for calling package

Однако обе у меня не работают вместе. Я пытался сохранить 100 файлов и оставил папку открытой, чтобы перекрестно проверить, из-за того, что быстрый процесс не позволяет мне видеть индикатор выполнения. Это не так. Есть предложения?

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Parallel.Invoke - это метод блокировки. Если вы вызываете его из потока пользовательского интерфейса, произойдет взаимоблокировка, потому что метод fileIteration вызывает обратно поток пользовательского интерфейса, чтобы обновить индикатор выполнения. Так что все застрянет.

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

Я предлагаю отказаться от махинаций Parallel.Invoke и Invoke(new MethodInvoker и принять async / await :

private async void Button1_Click(object sender, EventArgs e)
{
    int filesCountInit = await GetFilesCountAsync();
    if (filesCountInit == 0) return;
    progressBar1.Value = 0;
    var ssisTask = Task.Run(() => _package.Execute());
    while (!ssisTask.IsCompleted)
    {
        await Task.WhenAny(ssisTask, Task.Delay(1000));
        int filesCount = await GetFilesCountAsync();
        int percentDone = Math.Max(0, 100 - (filesCount * 100 / filesCountInit));
        progressBar1.Value = percentDone;
    }
    if (ssisTask.Status == TaskStatus.RanToCompletion)
        progressBar1.Value = 100;
    var results = await ssisTask;
    // Display the results
}

private Task<int> GetFilesCountAsync()
{
    return Task.Run(() => Directory.GetFiles(
        _folderPath, "*.*", SearchOption.TopDirectoryOnly).Length);
}
0 голосов
/ 27 мая 2020

Parallel.Invoke НЕ обеспечивает параллельное выполнение.

[...] Выполняет каждое из предоставленных действий, ВОЗМОЖНО параллельно. [...]

https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.parallel.invoke?view=netcore-3.1

Попробуйте создать явный поток, чтобы обеспечить параллельное выполнение фрагмента кода монитора выполнения.

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