新线程仍在阻止UI-Thread

时间:2022-08-27 20:57:36

when a button is clicked i start a seperate thead which is population a grid and does something with a webbrowser-control. But when the button is click the new thread seems not to be seperate, cause the UI is freezing until the new thread is done.

当单击一个按钮时,我启动一个单独的thead,它是一个网格,并使用webbrowser-control做一些事情。但是当单击该按钮时,新线程似乎不是单独的,导致UI冻结,直到新线程完成。

Here the code:

这里的代码:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    FindCustomerLocation()
    e.Handled = True
End Sub


Private Sub FindCustomerLocation()
    Dim Findcontractor_Thread As New Thread(AddressOf FindContractor_ThreadExecute)
    Findcontractor_Thread.Priority = ThreadPriority.AboveNormal
    Findcontractor_Thread.Start()
End Sub


Delegate Sub FindContractorDelegate(ByVal igGrid As Infragistics.Windows.DataPresenter.XamDataGrid, ByVal webbrowser As Controls.WebBrowser)


Private Sub FindContractor_ThreadExecute()
    Dim threadControls(1) As Object
    threadControls(0) = Me.XamDataGrid1
    threadControls(1) = Me.WebBrowserMap

    Dim m As FindContractorDelegate = AddressOf FindContractor_WorkingThread
    Me.Dispatcher.BeginInvoke(m, threadControls)
End Sub


Private Sub FindContractor_WorkingThread()

    Mouse.OverrideCursor = Cursors.Wait

'Do something...

    Mouse.OverrideCursor = Nothing
End Sub

What I'm doing wrong?

我做错了什么?

Thanks, Neils

4 个解决方案

#1


You propabldy working with the winforms controls in the "'do something". The controls can be mainupulated only in UI thread.

您可以在“'做某事'中使用winforms控件。控件只能在UI线程中进行主要设置。

So, the "BeginInvoke" call the target in ths UI thread. So you create te paralel thread, but the whole think is doing in UI thread again.

因此,“BeginInvoke”在UI线程中调用目标。所以你创建te paralel线程,但整个想法再次在UI线程中。

#2


Use Dispatcher.CurrentDispatcher.BeginInvoke to solve this problem.

使用Dispatcher.CurrentDispatcher.BeginInvoke来解决此问题。

The issue occurs because the Dispatcher instance invokes on the GUI thread but Dispatcher.CurrentDispatcher will create a new Dispatcher instance for the current executing thread if one does not exist.

出现此问题的原因是Dispatcher实例在GUI线程上调用,但Dispatcher.CurrentDispatcher将为当前正在执行的线程创建一个新的Dispatcher实例(如果不存在)。

This is similar in concept to how Windows will create message queues for new threads that are created that themselves create a winform.

这与Windows将如何为创建自己创建winform的新线程创建消息队列的概念类似。

#3


Dim Findcontractor_Thread As New Thread(AddressOf FindContractor_ThreadExecute)
Findcontractor_Thread.Priority = ThreadPriority.AboveNormal
Findcontractor_Thread.Start()

for threads calls with parameters

用于带参数的线程调用

trd_copy.ParameterizedStart(src)

Delegate Sub nameofDelegate(s As Integer)
Sub nameofDelegate+NameofSub(ByVal s As Integer)
If Form1.ProgressBar1.InvokeRequired Then
    Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
    NameOfYourForm.Invoke(d, New Object() {s})
Else
    If s = 1 Then
        NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
    Else

    End If
End If

End Sub

For Thread calls without parametrs

对于没有参数的线程调用

trd_copy.Start()

Delegate Sub nameofDelegate()
Sub nameofDelegate+NameofSub()
If Form1.ProgressBar1.InvokeRequired Then
    Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
    NameOfYourForm.Invoke(d, New Object())
Else
   NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
End If
End Sub

Keep in mind when you first Start a Thread and you are coding in a Model you MUST pass (me) into the initial thread because of VB having a concept of "Default Form Instances". For every Form in the application's namespace, there will be a default instance created in the My namespace under the Forms property.

请记住,当您第一次启动一个线程并且您正在编写模型时,您必须将(我)传递给初始线程,因为VB具有“默认表单实例”的概念。对于应用程序命名空间中的每个Form,将在Forms属性下的My命名空间中创建一个默认实例。

and that is just adding an additional parameter like so

这只是添加一个额外的参数

Private Sub FindCustomerLocation()
Dim Findcontractor_Thread As New Thread(AddressOf FindContractor_ThreadExecute)
Findcontractor_Thread.Priority = ThreadPriority.AboveNormal
Findcontractor_Thread.Start(me)
End Sub



Private Sub FindContractor_ThreadExecute(beginform as *NameOfFormComingFrom*)
Dim threadControls(1) As Object
threadControls(0) = Me.XamDataGrid1
threadControls(1) = Me.WebBrowserMap


FindContractor_WorkingThread(threadControls,beginform)
End Sub


Delegate Sub FindContractor_WorkingThread(s As Integer,beginform as   *NameOfFormComingFrom*)
Sub FindContractor_WorkingThreadInvoke(ByVal s As Integer,beginform as *NameOfFormComingFrom*)
If beginform.mouse.InvokeRequired Then
    Dim d As New FindContractor_WorkingThread(AddressOf    FindContractor_WorkingThreadInvoke)
    beginform.Invoke(d, New Object() {s,beginform})
Else
     beginform.Mouse.OverrideCursor = Cursors.Wait

    'Do something...

    beginform.Mouse.OverrideCursor = Nothing
End If
End Sub

#4


Your new thread has a higher priority, so will cause the UI to freeze whatever it does (as long as it is partly intensive)

您的新线程具有更高的优先级,因此将导致UI冻结它所做的任何事情(只要它是部分密集的)

#1


You propabldy working with the winforms controls in the "'do something". The controls can be mainupulated only in UI thread.

您可以在“'做某事'中使用winforms控件。控件只能在UI线程中进行主要设置。

So, the "BeginInvoke" call the target in ths UI thread. So you create te paralel thread, but the whole think is doing in UI thread again.

因此,“BeginInvoke”在UI线程中调用目标。所以你创建te paralel线程,但整个想法再次在UI线程中。

#2


Use Dispatcher.CurrentDispatcher.BeginInvoke to solve this problem.

使用Dispatcher.CurrentDispatcher.BeginInvoke来解决此问题。

The issue occurs because the Dispatcher instance invokes on the GUI thread but Dispatcher.CurrentDispatcher will create a new Dispatcher instance for the current executing thread if one does not exist.

出现此问题的原因是Dispatcher实例在GUI线程上调用,但Dispatcher.CurrentDispatcher将为当前正在执行的线程创建一个新的Dispatcher实例(如果不存在)。

This is similar in concept to how Windows will create message queues for new threads that are created that themselves create a winform.

这与Windows将如何为创建自己创建winform的新线程创建消息队列的概念类似。

#3


Dim Findcontractor_Thread As New Thread(AddressOf FindContractor_ThreadExecute)
Findcontractor_Thread.Priority = ThreadPriority.AboveNormal
Findcontractor_Thread.Start()

for threads calls with parameters

用于带参数的线程调用

trd_copy.ParameterizedStart(src)

Delegate Sub nameofDelegate(s As Integer)
Sub nameofDelegate+NameofSub(ByVal s As Integer)
If Form1.ProgressBar1.InvokeRequired Then
    Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
    NameOfYourForm.Invoke(d, New Object() {s})
Else
    If s = 1 Then
        NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
    Else

    End If
End If

End Sub

For Thread calls without parametrs

对于没有参数的线程调用

trd_copy.Start()

Delegate Sub nameofDelegate()
Sub nameofDelegate+NameofSub()
If Form1.ProgressBar1.InvokeRequired Then
    Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
    NameOfYourForm.Invoke(d, New Object())
Else
   NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
End If
End Sub

Keep in mind when you first Start a Thread and you are coding in a Model you MUST pass (me) into the initial thread because of VB having a concept of "Default Form Instances". For every Form in the application's namespace, there will be a default instance created in the My namespace under the Forms property.

请记住,当您第一次启动一个线程并且您正在编写模型时,您必须将(我)传递给初始线程,因为VB具有“默认表单实例”的概念。对于应用程序命名空间中的每个Form,将在Forms属性下的My命名空间中创建一个默认实例。

and that is just adding an additional parameter like so

这只是添加一个额外的参数

Private Sub FindCustomerLocation()
Dim Findcontractor_Thread As New Thread(AddressOf FindContractor_ThreadExecute)
Findcontractor_Thread.Priority = ThreadPriority.AboveNormal
Findcontractor_Thread.Start(me)
End Sub



Private Sub FindContractor_ThreadExecute(beginform as *NameOfFormComingFrom*)
Dim threadControls(1) As Object
threadControls(0) = Me.XamDataGrid1
threadControls(1) = Me.WebBrowserMap


FindContractor_WorkingThread(threadControls,beginform)
End Sub


Delegate Sub FindContractor_WorkingThread(s As Integer,beginform as   *NameOfFormComingFrom*)
Sub FindContractor_WorkingThreadInvoke(ByVal s As Integer,beginform as *NameOfFormComingFrom*)
If beginform.mouse.InvokeRequired Then
    Dim d As New FindContractor_WorkingThread(AddressOf    FindContractor_WorkingThreadInvoke)
    beginform.Invoke(d, New Object() {s,beginform})
Else
     beginform.Mouse.OverrideCursor = Cursors.Wait

    'Do something...

    beginform.Mouse.OverrideCursor = Nothing
End If
End Sub

#4


Your new thread has a higher priority, so will cause the UI to freeze whatever it does (as long as it is partly intensive)

您的新线程具有更高的优先级,因此将导致UI冻结它所做的任何事情(只要它是部分密集的)