难道从来没人遇到这个恶心的问题么?报错还是在主程序入口下抛出,初步调查来自MSDN解释:"DoWork 事件处理程序中的代码有可能在发出取消请求时完成其工作,轮询循环可能会错过设置为 true 的 CancellationPending。在这种情况下,即使发出了取消请求,RunWorkerCompleted 事件处理程序中 System.ComponentModel.RunWorkerCompletedEventArgs 的 Cancelled 标志也不会设置为 true。这种情况被称作争用状态,它是多线程编程中的常见问题。"我认为是这样的,我的dowork里任务十分繁重,代码巨长,涉及到文件批量拷贝,生成,图片的修改.我的取消按钮调用CancelAsync();完全按照MSDN上的写法DoWork里调用了如下方法private void Begin_Converter(BackgroundWorker worker, DoWorkEventArgs e)
{
if (!this.AllReady)
{
MessageBox.Show(this, "未准备好进行转换,请重新读取文件列表!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
CreateDir();
for (int i = 0; i < SourceFiles.Count; i++)
{
if (!worker.CancellationPending)
{
string path = SourceFiles[i];
string str2 = TargetFiles[i];
if (!File.Exists(path))
{
switch (MessageBox.Show(this, string.Format("文件{0}不存在!", path), "文件未找到", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Hand))
{
case DialogResult.Abort:
//MessageBox.Show(this, "转换中止!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Hand);
e.Result="转换中止!";
bgworkerConvert.CancelAsync();
return;
case DialogResult.Ignore:
{
continue;
}
case DialogResult.Retry:
{
i--;
continue;
}
}
}
if (File.Exists(str2) && !this.bOverlay)
{
//MessageBox.Show(this, "当前选定的目标目录已经有同名文件,请选择其它目录。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
//showAlert("当前选定的目标目录已经有同名文件,请选择其它目录。", "提示");
e.Result = "当前选定的目标目录已经有同名文件,请选择其它目录。";
deleteCreatedDir();
bgworkerConvert.CancelAsync();
return;
}
if (this.bSinglePage && !this.bResize)
{
if (this.bDelSource && (path != str2))
{
File.Move(path, str2);
}
else
{
File.Copy(path, str2, false);
}
}
else
{
if (this.bSinglePage)
{
this.procSinglePage(path, str2, worker, e);
}
else if (this.bDoublePage)
{
this.procDoublePage(path, str2, worker, e);
}
else if (this.bAuto)
{
Image image = Image.FromFile(path);
int height = image.Height;
int width = image.Width;
image.Dispose();
if (height >= width)
{
if (bResize)
{
procSinglePage(path, str2, worker, e);
}
else
{
File.Copy(path, str2, this.bOverlay);
}
}
if (height < width)
{
procDoublePage(path, str2, worker, e);
}
}
if (this.bDelSource)
{
File.Delete(path);
}
if (progressBar1.Value < progressBar1.Maximum)
{
worker.ReportProgress(i+1);
}
}
}
else
{
e.Cancel = true;
return;
}
}
e.Result = "转换完成";
}
各种取消方法都用过了,要么抛出淫荡的"调用的目标发生了异常",要么就是RunWorkerCompleted里压根无法判断BackgroundWorker到底是被取消了还是成功了!真是头疼的要死
{
if (!this.AllReady)
{
MessageBox.Show(this, "未准备好进行转换,请重新读取文件列表!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
CreateDir();
for (int i = 0; i < SourceFiles.Count; i++)
{
if (!worker.CancellationPending)
{
string path = SourceFiles[i];
string str2 = TargetFiles[i];
if (!File.Exists(path))
{
switch (MessageBox.Show(this, string.Format("文件{0}不存在!", path), "文件未找到", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Hand))
{
case DialogResult.Abort:
//MessageBox.Show(this, "转换中止!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Hand);
e.Result="转换中止!";
bgworkerConvert.CancelAsync();
return;
case DialogResult.Ignore:
{
continue;
}
case DialogResult.Retry:
{
i--;
continue;
}
}
}
if (File.Exists(str2) && !this.bOverlay)
{
//MessageBox.Show(this, "当前选定的目标目录已经有同名文件,请选择其它目录。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
//showAlert("当前选定的目标目录已经有同名文件,请选择其它目录。", "提示");
e.Result = "当前选定的目标目录已经有同名文件,请选择其它目录。";
deleteCreatedDir();
bgworkerConvert.CancelAsync();
return;
}
if (this.bSinglePage && !this.bResize)
{
if (this.bDelSource && (path != str2))
{
File.Move(path, str2);
}
else
{
File.Copy(path, str2, false);
}
}
else
{
if (this.bSinglePage)
{
this.procSinglePage(path, str2, worker, e);
}
else if (this.bDoublePage)
{
this.procDoublePage(path, str2, worker, e);
}
else if (this.bAuto)
{
Image image = Image.FromFile(path);
int height = image.Height;
int width = image.Width;
image.Dispose();
if (height >= width)
{
if (bResize)
{
procSinglePage(path, str2, worker, e);
}
else
{
File.Copy(path, str2, this.bOverlay);
}
}
if (height < width)
{
procDoublePage(path, str2, worker, e);
}
}
if (this.bDelSource)
{
File.Delete(path);
}
if (progressBar1.Value < progressBar1.Maximum)
{
worker.ReportProgress(i+1);
}
}
}
else
{
e.Cancel = true;
return;
}
}
e.Result = "转换完成";
}
各种取消方法都用过了,要么抛出淫荡的"调用的目标发生了异常",要么就是RunWorkerCompleted里压根无法判断BackgroundWorker到底是被取消了还是成功了!真是头疼的要死
bgworkerConvert.CancelAsync();
return;
应该写成
e.Cancel = true;
return;然后在
RunWorkerCompleted中判断e.Cancel即可
谢谢,你这个想法的缺点是:RunWorkerCompleted完全判断不出你这是取消的
你不能在doWork函数里面调上面那个函数.bgworkerconvert是主线程的控件,你在异步执行
的线性程调用其函数不报异常才怪了,所有调用这个函数据的地直接return ,并且将e.cancel置为true不就得了
我的调用方法是这样:
private void bgworkerConvert_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Begin_Converter(worker, e); }
都传递进去了的.这是按照MSDN上一个例子做的呀.使用
e.Cancel = true;
return;
的结果就是,"调用的目标发生了异常"
我把里面的东西全注释掉就不会再出这个问题,但是这么解决呢
private void bgworkerConvert_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
return;
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
//showAlert("任务终止","转换任务已经被用户终止");
//showAlert("任务终止", e.Result.ToString());
MessageBox.Show(this, e.Result.ToString(), "任务取消", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
else
{
// Finally, handle the case where the operation
// succeeded.
if (this.progressBar1.Value > 0)
{
//showAlert("转换成功", e.Result.ToString());
MessageBox.Show(this, e.Result.ToString(), "完成", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
goto lable_status;
}
}
if (e.Result.ToString().Length!=0)
{
showAlert("提示", e.Result.ToString());
} lable_status:
CtrlStatus(true, "convert");
}
全部函数renturn 线程自动结束,不要终止了,加个标记判断一下终止了,前台再操作终止后的情况。