vb.net 线程托管 窗口假死

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vb.net 线程托管 窗口假死相关的知识,希望对你有一定的参考价值。

不是说写了多线程之后,窗口就不会假死了吗?怎么我的还是假死啊?
过路的大侠帮忙看看:
一个窗体有两个richtextbox,创建了两个线程分别循环写这两个richtextbox
Imports System
Imports system.Threading
Public Class Form1
Delegate Sub dg(ByVal textt As String)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim th As New Thread(New ThreadStart(AddressOf method1))
th.Start()
Dim th1 As New Thread(New ThreadStart(AddressOf method2))
th1.Start()
End Sub
Public Sub method1()
Dim i As Long = 1
While (1)
settext("method 1 :" & i & vbCrLf)
i += 1
End While
End Sub
Public Sub method2()
Dim i As Long = 1
While (1)
settext1("method 2 :" & i & vbCrLf)
i += 1
End While
End Sub
Public Sub settext(ByVal i As String)
If Me.RichTextBox1.InvokeRequired Then
Dim d As New dg(AddressOf settext)
Me.Invoke(d, i)
Else
Me.RichTextBox1.Text = i & RichTextBox1.Text
End If
End Sub
Public Sub settext1(ByVal i As String)
If Me.RichTextBox2.InvokeRequired Then
Dim d As New dg(AddressOf settext1)
Me.Invoke(d, i)
Else
Me.RichTextBox2.Text = i & Me.RichTextBox2.Text
End If
End Sub
End Class
注意:我这里给出的是新建两个线程去操作窗体,不是新建“一个”线程。

我也很清楚问题是出在循环中不断调用me.invoke(d,i)导致的假死,可是我还是不清楚这段代码怎么改,能否帮忙改一下?
====================================================================
多谢,可是如果去掉thread.sleep(30)还是会假死,怎么解决啊?

参考技术A Me.Invoke(d, i)
问题出在这里!
直接用Me.Invoke把实际的执行任务提交给主线程运行
所以你的处理函数实际上是在主线程中运行的,新线程等于没用

正确的作法是,定义一个函数为入口的线程,并启动它
在需要调用的时候再使用Invoke来调用委托来进行更改。
----------------------------------------------------------------
方法已经给你说明白了,新建1个线程和2个线程来操作有什么不通用的哪??
问题不是线程个数的问题,是你线程中的函数一直在调用settext和settext1两个函数,而这两个函数都是处于method 方法 的while的循环中,相当于不间歇的在使用 Me.Invoke(d, i)这个方法。
----------------------------------------------------------------
如果你要不停地通过另外一个线程修改richtextbox内的内容,那也可以新启动一个线程,由这个线程的入口方法创建一个richtextbox ,再由这个线程来对这个richtextbox 进行操作。当然,你也可以用不安全的线程间的操作方法来实现。
参考技术B ======================================
因为代码的执行速度N快 你又用If Me.RichTextBox1.InvokeRequired Then
所以 这边在执行 那边也执行 导致冲突(貌似是这样的意思 我也说不清楚)
======================================

可以用委托去完成操作 保证不假死
我刚好之前有个实验实例 你可以看看

Imports System.Threading
Public Class Form1
Delegate Sub dg(ByVal textt As String)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t1 As New Thread(New ThreadStart(AddressOf ds1))
t1.Start()
Dim t2 As New Thread(New ThreadStart(AddressOf ds2))
t2.Start()
End Sub
Sub ds1()
For i As Integer = 0 To 3000
Me.BeginInvoke(New EventHandler(AddressOf ds11), i)
Thread.Sleep(30)
Application.DoEvents()
Next
End Sub
Sub ds11(ByVal sender As System.Object, ByVal e As System.EventArgs)
ListBox1.Items.Add(sender.ToString & Chr(6) & TextBox1.Text)
End Sub
Sub ds2()
For i As Integer = 0 To 3000
Me.BeginInvoke(New EventHandler(AddressOf ds22), i)
Thread.Sleep(30)
Application.DoEvents()
Next
End Sub
Sub ds22(ByVal sender As System.Object, ByVal e As System.EventArgs)
TextBox1.Text = sender.ToString
End Sub
End Class本回答被提问者采纳

如何在打开对话框的表单窗口顶部打开 VB.Net 对话框窗口?

【中文标题】如何在打开对话框的表单窗口顶部打开 VB.Net 对话框窗口?【英文标题】:How to open VB.Net dialog window on top of form window that is opening the dialog? 【发布时间】:2021-12-12 05:03:54 【问题描述】:

在我的 Form1 类中,我有一个名为 beginProcessingItems() 的方法,它对项目列表进行操作。这个列表可能非常大,所以我在一个新线程中执行 beginProcessingItems 方法,如下所示:

Dim processThread As New Thread(AddressOf beginProcessingItems)
processThread.Start()

有时我需要显示一个对话框来从用户那里收集有关某个项目的其他信息。此对话框是在 beginProcessingItems() 方法中创建和打开的,该方法现在在与我的 Form1 窗口不同的线程中运行。

当我打开对话框时,它正在 Form1 窗口后面加载。我在其他堆栈帖子中尝试了各种建议,但最终都导致跨线程操作无效异常。

这是我当前必须打开对话框的代码:

Public Sub beginProcessingItems()  
    ' ..do stuff .. and sometimes:
    Dim IDD As New ItemDetailsDialog()
    IDD.Location = ImportItemsButton.Location ' sets X,Y coords
    IDD.StartPosition = FormStartPosition.Manual
    IDD.TopMost = True
    'Note: Me = The Form1 object
    'IDD.Parent = Me '<-- also throws exception.
    If IDD.ShowDialog(Me) = DialogResult.OK Then ' <-- If I remove "Me" then the dialog opens but its underneath the Form1 window.
       ' .. do stuff with the dialog results
    End If
End Sub

这是异常消息:

跨线程操作无效:控件“Form1”从 线程不是创建它的线程。

【问题讨论】:

是的,一旦您开始尝试进行任何类型的 UI 交互,您就会 100% 遇到后台线程问题。您确实需要通过您的收集所有要求并将其传递到线程中。或者,也许迁移到更新的 Async/Await 模式可能会简化您的 UI 要求 【参考方案1】:

我能够将代码放入使用委托的工作中。

在 Form1 类中,我添加了:

' = Created a public property to hold the dialog object ======
Public IDD As ItemDetailDialog = Nothing

' = Created a Delegate ======
Delegate Sub DelegateShowItemDetailDialog(ByVal Param1 As Integer, ByRef SomeClassObj As SomeClass, ByVal Param3 As Integer)

' = Created a method that instantiates the IDD  property and shows the dialog =====
Private Sub ShowItemDetailDialog(ByVal Param1 As Integer, ByRef SomeClassObj As SomeClass, ByVal Param3 As Integer)
    IDD = New ItemDetailDialog(Param1, SomeClassObj, Param3)
    IDD.Location = ImportItemsButton.Location ' sets X,Y coords
    IDD.StartPosition = FormStartPosition.Manual
    'IDD.TopMost = True ' <-- not needed
    'IDD.Parent = Me ' <-- not needed
    IDD.ShowDialog()        
End Sub

' = Instantiate the Delegate object into a public property 
' = that will get invoked from the beginProcessingItems() method running in a separate thread
Public ThreadShowItemDetailDialog As New  DelegateShowItemDetailDialog(AddressOf ShowItemDetailDialog)

我修改了 beginProcessingItems 方法如下:

Public Sub beginProcessingItems()  
    ' ..do stuff .. and sometimes:
    Me.Invoke(ThreadShowItemDetailsDialog, Param1, SomeClassObj, Param3)
    ' dialog is now on top of the form1 window :-)
    If IDD.DialogResult = DialogResult.OK Then
       ' .. do stuff with the dialog results via the IDD class object
    End If
End Sub

请注意,Param1、SomeClassObj 和 Param3 变量显示为如何将参数值传递给对话框对象的示例。显然,您可以将它们更改为您的对话框对象实例化器所需的任何内容。

【讨论】:

【参考方案2】:

尝试将其放入您的 Sub Form_Load:

CheckForIllegalCrossThreadCalls = False

【讨论】:

以上是关于vb.net 线程托管 窗口假死的主要内容,如果未能解决你的问题,请参考以下文章

vb.net 多线程调用另一窗口,假死现象,如何解决

vb.net多线程,循环导致窗口界面假死的问题

vb.net 多线程 窗体 假死

我用C# winform多线程,窗口就假死,等到线程全部完成了才可以点击。请问要怎么才可以让窗口不假死。

C#程序窗口假死

delphi 用线程显示主线程窗口然后挂起自己就会假死。怎么解决?