Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 为什么此工作线程/线程没有停止?_Vb.net_Multithreading_Backgroundworker - Fatal编程技术网

Vb.net 为什么此工作线程/线程没有停止?

Vb.net 为什么此工作线程/线程没有停止?,vb.net,multithreading,backgroundworker,Vb.net,Multithreading,Backgroundworker,我有一个面板,其中有几个组合框和一个按钮来关闭面板。我设置了组合框来填充另一个线程,因为它有许多条目。因此,后台工作程序将启动,一切按预期进行,直到您关闭面板。如果在后台工作程序完成之前关闭面板,则会出现错误。让我解释一下: 我通过启动后台工作程序启动以下过程: get_info.RunWorkerAsync() “关闭”按钮子项如下所示: Private Sub close_everything() ' dispose of the panel that holds the comb

我有一个面板,其中有几个组合框和一个按钮来关闭面板。我设置了组合框来填充另一个线程,因为它有许多条目。因此,后台工作程序将启动,一切按预期进行,直到您关闭面板。如果在后台工作程序完成之前关闭面板,则会出现错误。让我解释一下:

我通过启动后台工作程序启动以下过程:

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
我这样设置后台工作人员:

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
然后,用于填充姓氏的子例程如下所示:

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
当按下close按钮时,我得到一个错误,说明combobox已被释放。因此,我首先添加了一个后台工作人员的检查。因此,我的代码更改为:

     ' 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。那么,如果它是真的,为什么它要执行下一行呢


如何阻止这种情况发生?

首先尝试停止后台工作程序:

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

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


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

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

我认为错误是因为您试图处理已处理的内容(即问题在于
关闭所有内容
)。您能否确认异常出现在哪个范围内?close_everything子项只调用一次。错误出现在我试图向组合框添加项目的行上。具体错误是:无法访问已释放的对象。对象名称:“组合框”。整个问题的出现是因为在同一个线程上向组合框添加27000个名称,而UI会让大多数人将界面挂起太长时间。这就是为什么我需要在另一个线程中实际填充列表。与填充combobox.bulk相比,获取名称的速度更快。您别无选择,只能将名称添加到UI线程上的组合框中,如您自己所示。你认为Invoke做什么?它将方法调用封送到拥有您调用它的控件的线程,即UI线程。您应该做的是调用AddRange一次,而不是在循环中反复添加。事实上,通过在循环中调用Invoke,您将使所有操作花费更长的时间,因为这样做会带来开销。除此之外,一份包含27000项的清单?恐怕这不是一个好的用户体验。我只是想一想——如果在添加条目时组合框不可见,并且当时它没有父项或所有者,那么有没有完成任何消息传递?您可以创建一个combobox实例,向线程发送信号,填充它,返回消息并在主线程中显示它?不知道-从未尝试过:)谢谢Martin,但组合框当时是可见的。我不知道你会怎么做。我现在还在寻找替代品。你为什么还在寻找替代品?您已经知道需要执行的操作。后台工作程序将在close_everything子例程中停止。这就是问题的原因。