我有一个带有两个后台工作人员的按钮单击事件。
static DirectoryInfo[] MySubDirectories;
private void btnProcess_Click(object sender, EventArgs e)
{
btnProcess.Enabled = false;
btnDirectory.Enabled = false;
btnCancel.Visible = true;
btnCancel.Enabled = true;
btnCancel.Text = "Cancel";
MyProgressBar.Visible = true;
_FileProcessingWorker = new BackgroundWorker();
_FileProcessingWorker.WorkerReportsProgress = true;
_FileProcessingWorker.WorkerSupportsCancellation = true;
_FileProcessingWorker.DoWork += new DoWorkEventHandler(_FileProcessingWorker_DoWork);
_FileProcessingWorker.ProgressChanged += new ProgressChangedEventHandler(_FileProcessingWorker_ProgressChanged);
_FileProcessingWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_FileProcessingWorker_RunWorkerCompleted);
_FileInformationWorker = new BackgroundWorker();
_FileInformationWorker.WorkerReportsProgress = true;
_FileInformationWorker.WorkerSupportsCancellation = true;
_FileInformationWorker.DoWork += new DoWorkEventHandler(_FileInformationWorker_DoWork);
_FileInformationWorker.ProgressChanged += new ProgressChangedEventHandler(_FileInformationWorker_ProgressChanged);
_FileInformationWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_FileInformationWorker_RunWorkerCompleted);
if (BasePath != null)
{
_FileInformationWorker.RunWorkerAsync();
}
}
在第一个后台工作者中,我做的dowork事件中的_FileInformationWorker
private void _FileInformationWorker_DoWork(object sender, DoWorkEventArgs e)
{
MySubDirectories = GetDirectories(BasePath).ToArray();
}
然后是 GetDirectory 方法
private List<DirectoryInfo> GetDirectories(string basePath)
{
IEnumerable<string> str = MyGetDirectories(basePath);
List<DirectoryInfo> l = new List<DirectoryInfo>();
l.Add(new DirectoryInfo(basePath));
IEnumerable<DirectoryInfo> dirs = str.Select(a => new DirectoryInfo(a));
l.AddRange(dirs);
return l;
}
和 MyGetDirectory 方法
int countDirectories = 0;
private IEnumerable<string> MyGetDirectories(string basePath)
{
try
{
string[] dirs = Directory.GetDirectories(basePath);
countDirectories = countDirectories + dirs.Length;
_FileInformationWorker.ReportProgress(countDirectories);
return dirs.Union(dirs.SelectMany(dir => MyGetDirectories(dir)));
}
catch (UnauthorizedAccessException)
{
return Enumerable.Empty<string>();
}
}
然后在第一个后台工作者进度更改事件中,我正在使用实时计数的目录数更新标签
private void _FileInformationWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label2.Text = e.ProgressPercentage.ToString();
}
现在,当第一个后台工作者工作时_FileInformationWorker我需要等到方法MyGetDirectory完成他的进程,仅在方法完成后获取所有目录,然后在DoWork事件中变量MySubDirectory不会为空。
但是,与其等待方法MyGetDirectory完成,我希望在DoWork事件中实时更新,或者以某种方式在progresschange事件中,带有目录的变量MySubDirectory已经实时获得。然后,当 MySubDirectory 即使长度为 1 或更多时,启动第二个后台工作线程并在 MySubDirectory 上工作。
并继续在第一个后台工作线程中更新 MySubDirectory,同时在第二个后台工作线程中继续处理它。
这是第二个后台工作人员办公事件:
private void _FileProcessingWorker_DoWork(object sender, DoWorkEventArgs e)
{
int countmore = 0;
try
{
DirectoryInfo[] MySubDirectories = (DirectoryInfo[])e.Argument;
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
{
DirectoryInfo MySubDirectory = MySubDirectories[i];
List<FileInfo> l = new List<FileInfo>();
CountFiles(MySubDirectory, l);
int totalFiles = l.Count;
object[] CurrentStatus = new object[5];
CurrentStatus[3] = i.ToString();
countmore += totalFiles;
CurrentStatus[4] = countmore;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
string CurrentDirectory = "Current Directory: " + MySubDirectory.Name;
foreach (FileInfo MyFile in l)
{
CurrentStatus = new object[5];
if (_FileProcessingWorker.CancellationPending)
{
e.Cancel = true;
return;
}
if (MyFile.Extension.ToLower() == ".cs" || MyFile.Extension.ToLower() == ".vb")
{
string CurrentFile = "Current File: " + MyFile.Name;
string CurrentFileWithPath = MyFile.FullName;
CurrentStatus[0] = CurrentDirectory;
CurrentStatus[1] = CurrentFile;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
List<string> Result = SearchInFile(CurrentFileWithPath, "ShellContextMenu");
if (Result != null && Result.Count > 0)
{
CurrentStatus[2] = Result;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
}
}
}
}
}
catch (Exception err)
{
return;
}
}
这就是我应该如何启动第二个后台工作者,但还不确定在哪里做,我曾经在按钮单击事件中这样做,但现在我需要在其他地方做一些事情,也许在第一个后台工作者做工作事件中?
int SubDirectoryCount = MySubDirectories.GetLength(0);
MyProgressBar.Minimum = 0;
MyProgressBar.Step = 1;
MyProgressBar.Maximum = SubDirectoryCount;
MyProgressBar.Value = MyProgressBar.Minimum;
_LastCounter = 0;
_FileProcessingWorker.RunWorkerAsync(MySubDirectories);
主要问题是如何实时更新第一个后台工作者中的变量 MySubDirectory,而不是等到后台工作者完成该过程。
以及如何以及在何处启动第二个后台工作线程,以及如何从最后一个点开始循环第二个后台工作线程中的 MySubDirectory 变量,而不是在目录上重新遍历,而只在最后一个添加的目录上循环。
您是否考虑过使用一些公共布尔变量?也许它可以帮助了解一个程序何时结束并且必须继续另一个程序。