Parallel.Invoke无法在C#中按预期方式工作

时间:2020-05-27 15:35:21

标签: c# ssis parallel-processing

我正在从C#代码中调用SSIS程序包。程序包一个接一个地处理文件,并将其从特定文件夹中删除。

程序包一个接一个地处理文件时,我想在进度栏中显示进度。

我已经编写了此函数来获取进度:

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 个答案:

答案 0 :(得分:1)

Parallel.Invoke是一种阻止方法。如果从UI线程调用它,则会发生死锁,因为fileIteration方法将回调UI线程以便更新进度条。所以一切都会卡住。

无论所提供的操作是由于正常终止还是由于异常终止而发生,此方法都不会返回,直到完成所有提供的操作为止。

我的建议是抛弃Parallel.InvokeInvoke(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);
}

答案 1 :(得分:0)

Parallel.Invoke不能确保并行执行。

[...]并行执行所有提供的动作。[...]

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

尝试生成显式线程,以确保并行执行进度监视器代码段。