关闭表单时如何在中间取消backgroundworker操作?
How do i cancel backgroundworker operation in the middle when closing the form?
我有这个 DoWork 事件代码:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bgw = (BackgroundWorker)sender;
if (bgw.CancellationPending == true)
{
return;
}
else
{
Bitmap newbmp = new Bitmap(512, 512);
IEnumerable<Point> CommonList = null;
StreamWriter w = new StreamWriter(@"c:\diff\diff.txt");
pixelscoordinatesinrectangle = new List<Point>();
pixelscoordinatesinrectangle = pointsAffected.ToList();
DrawIt = false;
for (int i = 0; i < trackBar1FileInfo.Length; i++)
{
DrawIt = true;
trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Value = i; }));
timer1.Stop();
Button1Code();
timer1.Start();
trackBar2.Invoke(new MethodInvoker(delegate { trackBar2.Enabled = false; }));
trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Enabled = false; }));
trackBar1.Invoke(new MethodInvoker(delegate { LoadPictureAt(trackBar1.Value, sender); }));
pictureBox1.Load(trackBar1FileInfo[i].FullName);
trackBar1.Invoke(new MethodInvoker(delegate {
ConvertedBmp = ConvertTo24(trackBar1FileInfo[trackBar1.Value].FullName);
}));
ConvertedBmp.Save(ConvertedBmpDir + "\ConvertedBmp.bmp");
mymem = ToStream(ConvertedBmp, ImageFormat.Bmp);
Button1Code();
pictureBox1.Invoke(new MethodInvoker(delegate { pictureBox1.Refresh(); }));
newpixelscoordinates = new List<Point>();
newpixelscoordinates = pointsAffected.ToList();
CommonList = pixelscoordinatesinrectangle.Intersect(newpixelscoordinates);
foreach (Point s in CommonList)
{
w.WriteLine("The following points are the same" + s);
newbmp.SetPixel(s.X, s.Y, Color.Red);
}
}
w.Close();
using (Graphics G = Graphics.FromImage(newbmp))
newbmp.Save(@"c:\newbmp\newbmp.bmp", ImageFormat.Bmp);
newbmp.Dispose();
}
}
问题是当 backgroundworker dowork 正在工作时,我在中间关闭了表单。
然后它每次都在 DoWork 事件异常的不同行上抛出:
无法访问已释放的对象
例如这一行:
trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Value = i; }));
我尝试在 FormClosing 事件中执行以下操作:
backgroundWorker2.CancelAsync();
但它什么也没做。
我已经在设计器中将 backgroundworker2 WorkerSupportsCancellation 设置为 true。
在循环中我试着这样做:
pictureBox1.Invoke(new MethodInvoker(delegate { pictureBox1.Refresh();
if (bgw.CancellationPending == true)
{
MessageBox.Show("cancelled");
}
}));
但我仍然没有收到异常消息:无法访问已处置的对象
尝试在循环之前和循环顶部添加此 bgw.CancellationPending 检查。在循环的每个地方我都在使用 Begin Invoke
但仍然在循环内的不同行上始终遇到此异常。
在我做的表格关闭事件中:
private void ScanClouds_FormClosing(object sender, FormClosingEventArgs e)
{
backgroundWorker2.WorkerSupportsCancellation = true;
backgroundWorker2.CancelAsync();
}
而且在关闭表单时我仍然遇到异常。
您只在 DoWork 代码中检查 bgw.CancellationPending == true
一次。您需要检查 每次 您从某个可以 "take a while" 的操作返回,例如,在您的每个 Invoke
调用之后(这可能是一个很好的尝试将其中一些组合成一个 Invoke
并在每次调用中做不止一件事的想法)
注意设置这个标志
bgw.CancellationPending = true
仅通知工作线程已请求取消。在 DoWork 中的线程检查此 bgw.CancellationPending 标志之前,实际上不会发生取消。
所以你需要检查你的循环
for (int i = 0; i < trackBar1FileInfo.Length; i++)
{
if(bgw.CancellationPending == false)
{
//...
}
}
我有这个 DoWork 事件代码:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bgw = (BackgroundWorker)sender;
if (bgw.CancellationPending == true)
{
return;
}
else
{
Bitmap newbmp = new Bitmap(512, 512);
IEnumerable<Point> CommonList = null;
StreamWriter w = new StreamWriter(@"c:\diff\diff.txt");
pixelscoordinatesinrectangle = new List<Point>();
pixelscoordinatesinrectangle = pointsAffected.ToList();
DrawIt = false;
for (int i = 0; i < trackBar1FileInfo.Length; i++)
{
DrawIt = true;
trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Value = i; }));
timer1.Stop();
Button1Code();
timer1.Start();
trackBar2.Invoke(new MethodInvoker(delegate { trackBar2.Enabled = false; }));
trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Enabled = false; }));
trackBar1.Invoke(new MethodInvoker(delegate { LoadPictureAt(trackBar1.Value, sender); }));
pictureBox1.Load(trackBar1FileInfo[i].FullName);
trackBar1.Invoke(new MethodInvoker(delegate {
ConvertedBmp = ConvertTo24(trackBar1FileInfo[trackBar1.Value].FullName);
}));
ConvertedBmp.Save(ConvertedBmpDir + "\ConvertedBmp.bmp");
mymem = ToStream(ConvertedBmp, ImageFormat.Bmp);
Button1Code();
pictureBox1.Invoke(new MethodInvoker(delegate { pictureBox1.Refresh(); }));
newpixelscoordinates = new List<Point>();
newpixelscoordinates = pointsAffected.ToList();
CommonList = pixelscoordinatesinrectangle.Intersect(newpixelscoordinates);
foreach (Point s in CommonList)
{
w.WriteLine("The following points are the same" + s);
newbmp.SetPixel(s.X, s.Y, Color.Red);
}
}
w.Close();
using (Graphics G = Graphics.FromImage(newbmp))
newbmp.Save(@"c:\newbmp\newbmp.bmp", ImageFormat.Bmp);
newbmp.Dispose();
}
}
问题是当 backgroundworker dowork 正在工作时,我在中间关闭了表单。 然后它每次都在 DoWork 事件异常的不同行上抛出:
无法访问已释放的对象
例如这一行:
trackBar1.Invoke(new MethodInvoker(delegate { trackBar1.Value = i; }));
我尝试在 FormClosing 事件中执行以下操作:
backgroundWorker2.CancelAsync();
但它什么也没做。
我已经在设计器中将 backgroundworker2 WorkerSupportsCancellation 设置为 true。
在循环中我试着这样做:
pictureBox1.Invoke(new MethodInvoker(delegate { pictureBox1.Refresh();
if (bgw.CancellationPending == true)
{
MessageBox.Show("cancelled");
}
}));
但我仍然没有收到异常消息:无法访问已处置的对象
尝试在循环之前和循环顶部添加此 bgw.CancellationPending 检查。在循环的每个地方我都在使用 Begin Invoke
但仍然在循环内的不同行上始终遇到此异常。
在我做的表格关闭事件中:
private void ScanClouds_FormClosing(object sender, FormClosingEventArgs e)
{
backgroundWorker2.WorkerSupportsCancellation = true;
backgroundWorker2.CancelAsync();
}
而且在关闭表单时我仍然遇到异常。
您只在 DoWork 代码中检查 bgw.CancellationPending == true
一次。您需要检查 每次 您从某个可以 "take a while" 的操作返回,例如,在您的每个 Invoke
调用之后(这可能是一个很好的尝试将其中一些组合成一个 Invoke
并在每次调用中做不止一件事的想法)
注意设置这个标志
bgw.CancellationPending = true
仅通知工作线程已请求取消。在 DoWork 中的线程检查此 bgw.CancellationPending 标志之前,实际上不会发生取消。
所以你需要检查你的循环
for (int i = 0; i < trackBar1FileInfo.Length; i++)
{
if(bgw.CancellationPending == false)
{
//...
}
}