等到我的BackgroundWorker完成,以打开新的BackgroundWorker
本文关键字:BackgroundWorker 我的 完成 | 更新日期: 2023-09-27 18:15:36
在我的应用程序中,我在添加到我的列表框之前通过打开Wireshark进程检查我的文件。这是添加目录,点击事件,查看根文件夹和子文件夹中的所有文件:
private void btnAddDir_Click(object sender, EventArgs e)
{
try
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
ThreadStart threadStart = delegate
{
foreach (string file in SafeFileEnumerator.EnumerateFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories))
{
Interlocked.Increment(ref numWorkers);
StartBackgroundFileChecker(file);
}
};
Thread thread = new Thread(threadStart);
thread.IsBackground = true;
thread.Start();
}
}
catch (Exception)
{ }
}
private void StartBackgroundFileChecker(string file)
{
ListboxFile listboxFile = new ListboxFile();
listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent;
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork +=
(s3, e3) =>
{
//check my file
};
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (Interlocked.Decrement(ref numWorkers) == 0)
{
//update my UI
}
}
当我检查这个文件时,我打开Wireshark
进程,所以如果我选择有许多文件的文件夹,许多Wireshark
进程打开,这需要很多内存,我怎么能等到我的BackgroundWorker完成,然后才打开新的?
据我所知,您希望每次只启动一个后台worker。如果是,那么尝试这个(基于System.Threading.AutoResetEvent)
//introduce additional field
private AutoResetEvent _workerCompleted = new AutoResetEvent(false);
//modify StartBackgroundFileChecker
private void StartBackgroundFileChecker(string file)
{
ListboxFile listboxFile = new ListboxFile();
listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent;
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork +=
(s3, e3) =>
{
//check my file
};
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
//new code - wait for completion
_workerCompleted.WaitOne();
}
//add completion notification to backgroundWorker_RunWorkerCompleted
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (Interlocked.Decrement(ref numWorkers) == 0)
{
//update my UI
}
//new code - notify about completion
_workerCompleted.Set();
}
在这个解决方案中,你的后台线程将一个接一个地启动新的BackgroundWorker——这可能不是最优的(你可以完全避免BackgroundWorker,只需通过threadStart delegate中的Dispatch来更新UI)
在我看来,最好控制并行线程的数量,并在多个线程中处理文件,但线程数量有限。
这是另一种解决方案(基于System.Threading.Tasks命名空间):
private void btnAddDir_Click(object sender, EventArgs e)
{
var selectedPath = folderBrowserDialog1.SelectedPath;
Task.Factory.StartNew(() =>
{
var files = Directory.EnumerateFiles(selectedPath, "*.*", SearchOption.AllDirectories);
Parallel.ForEach(files,
new ParallelOptions
{
MaxDegreeOfParallelism = 10 // limit number of parallel threads here
},
file =>
{
//process file here - launch your process
});
}).ContinueWith(
t => { /* when all files processed. Update your UI here */ }
,TaskScheduler.FromCurrentSynchronizationContext() // to ContinueWith (update UI) from UI thread
);
}
你可以根据你的具体需要调整这个解决方案。
使用的类/方法(参考MSDN):
- TaskScheduler。FromCurrentSynchronizationContext
- 平行。ForEach Method (IEnumerable, ParallelOptions, Action)
也许像这样,而不是foreach保留一个文件列表,完成后只取第一个元素并更新您的列表
private List<string> _files;
private void btnAddDir_Click(object sender, EventArgs e)
{
try
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
_files = new List<string>(SafeFileEnumerator.EnumerateFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories));
Interlocked.Increment(ref numWorkers);
var file = _files.FirstOrDefault();
if(file != null)
StartBackgroundFileChecker(file);
}
}
catch (Exception)
{ }
}
private void StartBackgroundFileChecker(string file)
{
ListboxFile listboxFile = new ListboxFile();
listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent;
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork +=
(s3, e3) =>
{
//check my file
};
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (Interlocked.Decrement(ref numWorkers) == 0)
{
//update my UI
_files = _files.Skip(1);
var file = _files.FirstOrDefault();
if(file != null)
StartBackgroundFileChecker(file);
}
}