简体   繁体   English

将结果从取消的BackgroundWorker线程传递回主线程

[英]Passing results back to main thread from a cancelled BackgroundWorker thread

How can I cancel a backgroundworker and pass back an error message. 如何取消背景工作人员并传回错误消息。 I know that you can use DoWorkEventArgs e.Results to pass back results to main thread but e.Results gets overwritten when I cancel the child thread. 我知道您可以使用DoWorkEventArgs e.Results将结果传递回主线程,但是当我取消子线程时, e.Results将被覆盖。 Example: 例:

private MyProgram_DoWork(object sender, DoWorkEventArgs e)
{
     e.Cancel = true;
     e.Result = "my error message";
     return;
}

private void MyProgram_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
     if ((e.Cancelled == true))
     { 
            string ErrorMsg = (string)e.Result;   //exception happens here 

            ....
     }
     else
     { 
          // success code
     }
}

Is there another way to stop my child thread and send a string back to the main thread? 还有另一种方法来停止我的子线程并将字符串发送回主线程吗?

If your long-running process was canceled, it wouldn't really have a "result", as the process didn't completely finish. 如果您取消了长期运行的流程,则该流程实际上不会产生“结果”,因为该流程并未完全完成。

According to the documentation : 根据文档

Your RunWorkerCompleted event handler should always check the Error and Cancelled properties before accessing the Result property. 您的RunWorkerCompleted事件处理程序应始终在访问Result属性之前检查Error和Canceled属性。 If an exception was raised or if the operation was canceled, accessing the Result property raises an exception. 如果引发异常或操作被取消,则访问Result属性将引发异常。

I took a peek inside BackgroundWorker . 我在BackgroundWorker内部进行了窥视。 Here's the contents of the Result property: 这是Result属性的内容:

public object Result
{
  get
  {
    this.RaiseExceptionIfNecessary();
    return this.result;
  }
}

And the contents of RaiseExceptionIfNecessary() : 以及RaiseExceptionIfNecessary()的内容:

protected void RaiseExceptionIfNecessary()
{
  if (this.Error != null)
    throw new TargetInvocationException(SR.GetString("Async_ExceptionOccurred"), this.Error);
  if (this.Cancelled)
    throw new InvalidOperationException(SR.GetString("Async_OperationCancelled"));
}

So if you cancel the thread, referencing Result will throw an InvalidOperationException . 因此,如果取消线程,则引用Result将抛出InvalidOperationException That's just the way it's designed. 那就是它的设计方式。

I don't know what the "best" way is to pass a string back. 我不知道“最好”的方法是将字符串传回。 I'd say you could define a variable in the same method you run the BackgroundWorker from, and assign a value to it from the DoWork event. 我想说,您可以使用与运行BackgroundWorker相同的方法来定义变量,并从DoWork事件中为其分配值。

You just have to be very careful that nothing on the UI thread is somehow bound to the variable or you could run into problems. 您只需要非常小心,即UI线程上的任何内容都不会以某种方式绑定到变量,否则您可能会遇到问题。 A string should be safe, but don't start adding to a list that's bound to a ComboBox or something. 字符串应该是安全的,但不要开始添加到绑定到ComboBox或其他内容的列表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM