我正在从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个文件并保持文件夹打开,以便进行交叉检查,快速的过程使我无法看到进度栏。事实并非如此。有什么建议吗?
答案 0 :(得分:1)
Parallel.Invoke
是一种阻止方法。如果从UI线程调用它,则会发生死锁,因为fileIteration
方法将回调UI线程以便更新进度条。所以一切都会卡住。
无论所提供的操作是由于正常终止还是由于异常终止而发生,此方法都不会返回,直到完成所有提供的操作为止。
我的建议是抛弃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);
}
答案 1 :(得分:0)
Parallel.Invoke不能确保并行执行。
[...]并行执行所有提供的动作。[...]
https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.parallel.invoke?view=netcore-3.1
尝试生成显式线程,以确保并行执行进度监视器代码段。