我有后台工作人员的问题。我有一个轨迹栏,当用户更改它的值时,就会启动一个新的后台工作程序。有一个所有后台工作人员的列表,当启动一个新工作人员时,列表中的所有工作人员都会调用worker.CancelAsync()
.
当用户在轨迹栏上进行缓慢更改时,它可以工作,但是当您快速移动它时,大约有 20 多个线程,并且需要一些时间才能在WorkerCompleted
. 此外,在这个函数中,工作变量正在清理(在这种情况下,这是位图的副本),所以 20 多个工作人员需要大量内存,我得到一个OutOfMemoryException
.
有什么方法可以将线程数阻塞到 4 左右,当后台工作程序的数量等于 4 时,程序将等待它们何时被删除,或者有什么方法可以只使用一个后台工作程序,并且当跟踪栏值改变它重新启动?
添加新工人:
public override void StartWorker(Bitmap bmp, bool needTempImage)
{
if(m_workersList.Count<maxThread)
{
CancelAllJobs();
// debug.Text = "locked";
BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
imageDataAttributes imgAttr = new imageDataAttributes(bd.Width, bd.Height, bd.Stride, 4);
ThreadWorker worker = new ThreadWorker(needTempImage, bd.Scan0, imgAttr);
bmp.UnlockBits(bd);
m_workersList.Add(worker);
m_currentWorker = worker;
worker.worker.WorkerSupportsCancellation = true;
worker.worker.DoWork += WorkerDoWork;
worker.worker.WorkerReportsProgress = report;
if (report == true)
{
worker.worker.ProgressChanged += WorkerProgress;
m_progressBar.Visible = true;
}
worker.worker.RunWorkerCompleted += WorkerCompleted;
worker.worker.RunWorkerAsync(worker);
debug.Text = "" + m_workersList.Count;
}
//debug.Text = "unlocked";
}
这是取消:
public override void CancelAllJobs()
{
foreach (ThreadWorker worker in m_workersList)
{
worker.cancelled = true;
worker.worker.CancelAsync();
}
debug.Text = "" + m_workersList.Count;
}
做工作:
protected override void WorkerDoWork(object sender, DoWorkEventArgs e)
{
ThreadWorker worker = (ThreadWorker)e.Argument;
if (worker.worker.CancellationPending == true)
{
e.Cancel = true;
worker.cancelled = true;
return;
}
WorkerProcessFun(worker);
}
工人完成:
protected override void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ThreadWorker worker = m_workersList.Find(w => w.worker == sender);
if (!worker.cancelled && worker == m_currentWorker)
{
if (e.Error != null)
{
MessageBox.Show("Worker Thread Error " + e.Error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
WorkerOnCompleteFun(worker.imgDataArray);
}
}
m_workersList.Remove(worker);
worker.Clean();
if (worker == m_currentWorker) m_currentWorker = null;
debug.Text = "" + m_workersList.Count;
}
ProcessMainFun 需要工人,因为有检查 CancelationPending,设置 e.Cancel=true; 并返回;
private void MainProcessFun(ThreadWorker worker)
{
Filters.Filters.AdvancedBlur(m_radius, m_sigma, worker);
}