C# 背景工人?
我有一个相当复杂的程序,所以我不会把整个东西都放在这里。以下是一个简化版本:C# 背景工人?,c#,multithreading,exception,backgroundworker,C#,Multithreading,Exception,Backgroundworker,我有一个相当复杂的程序,所以我不会把整个东西都放在这里。以下是一个简化版本: class Report { private BackgroundWorker worker; public Report(BackgroundWorker bgWorker, /* other variables, etc */) { // other initializations, etc worker = bgWorker; } private
class Report {
private BackgroundWorker worker;
public Report(BackgroundWorker bgWorker, /* other variables, etc */) {
// other initializations, etc
worker = bgWorker;
}
private void SomeCalculations() {
// In this function, I'm doing things which may cause fatal errors.
// Example: I'm connecting to a database. If the connection fails,
// I need to quit and have my background worker report the error
}
}
// In the GUI WinForm app:
// using statements, etc.
using Report;
namespace ReportingService {
public partial class ReportingService : Form {
// My background worker
BackgroundWorker theWorker = new BackgroundWorker() {
WorkerReportsProgress = true
};
// The progress changed event
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
// e.UserState and e.ProgressPercentage on some labels, etc.
}
// The do work event for the worker, runs the number crunching algorithms in SomeCalculations();
void worker_DoWork(object sender, DoWorkEventArgs e) {
Report aReport = e.Argument as Report;
aReport.SomeCalculations();
}
// The completed event, where all my trouble is. I don't know how to retrieve the error,
// or where it originates from.
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
// How, exactly, do I get this error message? Who provides it? How?
if (e.Error != null) {
MessageBox.Show("Error: " + (e.Error as Exception).ToString());
}
else if (e.Cancelled) {
MessageBox.Show("Canceled");
}
// operation succeeded
else {
MessageBox.Show("Success");
}
}
// Initialization of the forml, etc
public ReportingService() {
InitializeComponent();
theWorker.ProgressChanged += worker_ProgressChanged;
theWorker.DoWork += worker_DoWork;
theWorker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
// A button that the user clicks to execute the number crunching algorithm
private void sumButton_Click(object sender, EventArgs e) {
Report myReport = new Report(theWorker, /* some other variables, etc */)
theWorker.RunWorkerAsync(myReport);
}
}
}
这是我的逻辑,如果我走错了方向,请纠正我:
// My number crunching algorithm contained within my class calls a function which does this:
// try {
using (SqlConnection c = GetConnection()) { // note: I've corrupted the connection string on purpose
c.Open(); // I get the exception thrown here
using (SqlCommand queryCommand = new SqlCommand(query, c)) { /* Loop over query, etc. */ }
c.Close();
}
// } catch (Exception e) { }
一,。
据我所知,一个未处理的异常会被强制转换到RunWorkerCompletedEventArgs
的错误部分?当我尝试此方法时,我得到以下结果:
// In my winform application I initialize my background worker with these events:
void gapBW_DoWork(object sender, DoWorkEventArgs e) {
Report aReport = e.Argument as Report;
Report.Initialize(); // takes ~1 minute, throws SQL exception
Report.GenerateData(); // takes around ~2 minutes, throws file IO exceptions
}
void gapBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (e.Error != null) { // I can't get this to trigger, How does this error get set?
MessageBox.Show("Error: " + (e.Error as Exception).ToString());
}
else if (e.Cancelled) {
MessageBox.Show("Canceled: " + (e.Result).ToString());
}
else {
MessageBox.Show("Success");
}
}
Visual studio说我的应用程序因c.Open()
失败而阻塞,出现未处理的异常
二,。
当我在DoWork函数中放置try/catch块时:
void gapBW_DoWork(object sender, DoWorkEventArgs e) {
try {
Report aReport = e.Argument as Report;
aReport.Initialize(); // throws SQL exceptions
aReport.GenerateData(); // throws IO file exceptions
}
catch (Exception except) {
e.Cancel = true;
e.Result = except.Message.ToString();
}
}
void gapBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (e.Error != null) { // I can't get this to trigger, How does this error get set?
MessageBox.Show("Error: " + (e.Error as Exception).ToString());
}
else if (e.Cancelled) {
MessageBox.Show("Canceled: " + (e.Result).ToString());
}
else {
MessageBox.Show("Success");
}
}
我在自动生成的应用程序.Run(new ReportingService())的Program.cs中得到一个targetingException
未处理的异常代码>行。我在RunWorkerCompleted上放置了一个断点,可以看到e.Cancelled=true、e.Error=null和e.UserState=null。e.Cancelled中包含的消息只是“操作已取消”。我想象我从一个无效的e.Result强制转换(因为它是空的)接收到targetingException
。但是我想知道的是,为什么e.Error仍然为null,而e.cancelled没有包含任何关于为什么取消操作的有用信息
三,。
当我尝试设置e.cancelled=true时代码>在异常捕获的DoWork中,我设法触发了else if(例如取消){
我的RunWorkerCompleted
函数中的行。我认为这是为请求取消作业的用户保留的?我根本误解了后台工作人员的工作方式吗?如果发生任何错误,请在doEvent上的catch块中设置e.Cancel=true
。首先设置属性true
在嫁妆活动中
private void bw_DoWork( object sender, DoWorkEventArgs e )
{
try
{
if( !backgroundWorkder.CancellationPending )
{
// ....
}
}
catch
{
if (bgWorker.WorkerSupportsCancellation && !bWorker.CancellationPending)
{
e.Cancel = true;
e.Result = "Give your error";
return;
}
}
}
在方法上
如果您没有在DoEvent中执行任何异常处理,BackgroundWorker本身会为您执行此操作。
如果在异步操作期间引发异常,则类
将异常分配给错误属性。客户端
应用程序的事件处理程序委托应检查Error属性
在访问派生自的类中的任何属性之前
AsyncCompletedEventArgs;否则,该属性将引发
TargetInvocationException,其InnerException属性包含
对错误的引用
如果操作已取消,则Error属性的值为null
那样的话
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled the operation.
}
}
有关更多详细信息,请参阅。您的思路正确。在RunWorkerCompleted
事件中,e.Error参数包含引发的任何异常。在这种情况下,您应该处理
if (e.Error != null) {...}
作为运行后台工作程序的try
的catch块,如果有意义的话。每次在DoWork中的操作完成、取消或引发异常时,都会触发RunWorkerCompleted。然后在RunWorkerCompleted中,如果错误不为null,则检查RunWorkerCompletedEventArgs。错误属性自动设置为DoWork中出现en异常。在这种特殊情况下不需要try-catch
您的思路是正确的。我尝试了这个小测试程序,它的工作原理与预期相符:
static void Main(string[] args)
{
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => { throw new ArgumentException(); };
worker.RunWorkerCompleted += (sender, e) => Console.WriteLine(e.Error.Message);
worker.RunWorkerAsync();
Console.ReadKey();
}
但是,当我在调试器中运行此程序时,我在throw语句中也得到了关于未处理异常的消息。但我只是再次按下F5,它继续运行,没有任何问题。因此我不需要在我的报表类中尝试/捕获SQL查询?当我删除它时,我得到一个SqlException未被用户代码err处理或者。异常永远不会传播到my worker的工作完成?如果正在调试,只需按“继续”(默认情况下为F5)控件应该流入RunWorker完成的事件处理程序和e中。错误应该被填充。感谢大家的帮助,但这最终解决了我的问题。事实证明,问题不是我对C#的误解,而是我对Visual Studio的误解。我养成了按F5运行程序的习惯,并认为n异常未经处理,程序将崩溃。我不知道您可以再次按F5继续处理。另外,请不要忘记按F10、F11和Shift-F11的功能。;-)也许查看一下也能帮到您。
static void Main(string[] args)
{
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => { throw new ArgumentException(); };
worker.RunWorkerCompleted += (sender, e) => Console.WriteLine(e.Error.Message);
worker.RunWorkerAsync();
Console.ReadKey();
}