为什么这个工人/线程没有停止?

时间:2014-03-31 21:49:33

标签: vb.net multithreading backgroundworker

我有一个面板,里面有几个组合框,还有一个关闭面板的按钮。我设置组合框以填充另一个线程,因为它有许多条目。所以后台工作程序启动,一切都按预期进行,直到你关闭面板。如果我在后台工作程序完成之前关闭面板,则会出错。让我解释一下:

我开始启动后台工作程序的过程:

get_info.RunWorkerAsync()

关闭按钮子看起来像这样:

Private Sub close_everything()

   ' dispose of the panel that holds the comboboxes
   info_panel.dispose()

   ' tell the background worker to stop working
   get_info.CancelAsync()

End Sub

我像这样设置了后台工作者:

   Private Sub getInfo_doWork()
      'populate the combo boxes
      populate_last_names()        
   End Sub

然后填充姓氏的子程序如下所示:

Private Sub populate_last_names()
    ' get the names
      get_names()

     ' since the combobox control is in another thread, I need to use the Invoke method to access it
     ' put them in the combobox
     for a as integer = 0 to last_names.count - 1
         last_name_box.Invoke(Sub() last_name_box.Items.Add(last_names(a)))
     next
End Sub

按下关闭按钮时,出现错误,指出组合框已被丢弃。所以我先为后台工作者添加了一个检查。所以我的代码改为:

     ' put them in the combobox
     for a as integer = 0 to last_names.count - 1
         if not(get_info.CancellationPending) then
           last_name_box.Invoke(Sub() last_name_box.Items.Add(last_names(a)))
         end if
     next

但我仍然遇到同样的错误,所以我添加了另一张支票并将代码更改为:

     ' put them in the combobox
     for a as integer = 0 to last_names.count - 1
         if not(get_info.CancellationPending) then
           if not(last_name_box.IsDisposed) then
             last_name_box.Invoke(Sub() last_name_box.Items.Add(last_names(a)))
           end if
         end if
     next

如果我在循环结束前关闭面板,我仍然会收到一条错误,指出last_name框已被释放。

错误甚至表明last_name_box.IsDisposed的值为TRUE且CancellationPending的值为TRUE。那么,如果它为TRUE,为什么还要执行下一行呢?

如何阻止这种情况发生?

3 个答案:

答案 0 :(得分:0)

首先尝试停止后台工作人员:

Private Sub close_everything()

   ' tell the background worker to stop working
   get_info.CancelAsync()

   ' dispose of the panel that holds the comboboxes
   info_panel.dispose()

End Sub

答案 1 :(得分:0)

您的代码构造错误。您应该做的是在DoWork事件处理程序中获取数据,然后通过e.Result属性将其传递给RunWorkerCompleted事件处理程序。然后使用RunWorkerCompleted事件处理程序中的数据填充控件,该事件处理程序在UI线程上执行。

您也不应该将Panel隐藏在RunWorkerCompleted事件处理程序中的任何位置。您从UI线程请求取消,然后您实际在DoWork事件处理程序中执行取消。在RunWorkerCompleted事件处理程序中,检查操作是否已取消。如果是,则只需隐藏Panel,否则填充列表。

答案 2 :(得分:0)

由于我的问题的可行答案似乎不可能,我最终切换到带有自动填充的文本框而不是带有自动填充的组合框。我只是因为自动填充功能而使用组合框,并没有意识到文本框可以做同样的事情。数据在后台工作程序中收集,并且在主UI中收集数据后分配自动填充的源。我无法完成我想要的东西,所以我为此付出了代价。仍有一些延迟,但它是可以控制的。

相关问题