.net - 在 Invoke() 内部运行时,跨线程操作对表单控件无效 - .NET

标签 .net vb.net multithreading invoke

我正在使用 VB.NET 4.8.1 我创建了一个函数 InvokeIfNecessary(action),它检查它是否在 UI 线程上运行,如果没有,则调用主窗体。

Public Sub InvokeIfNecessary(act As Action)
    If IsUIThread() Then
        act()
    Else
        Application.OpenForms(0).Invoke(act)
    End If
End Sub

因为它运行得非常好,所以我开始用这个简单的函数替换我困惑的 .InvokeRequired 和其他检查。但是我刚刚收到错误“跨线程操作无效:从创建它的线程以外的线程访问控制'PB_ItemImage'。”

下面的代码在 _img.Visible=false 时失败。我之前已暂停执行以确认它正在 UI 线程中运行。该变量引用了我在设计器中创建的 PictureBox,因此显然它也应该位于 UI 线程中。 (我还确认该函数不在 UI 线程上,因此它正在使用 Invoke 函数。)

Public Function ImgDisplayFromFile(ByRef img As PictureBox, imgFileName As String, Optional safe As Boolean = False)
    Dim _img = img
    If Not _img.IsDisposed Then InvokeIfNecessary(Sub()
                                                      MsgBox(IsUIThread()) 'This confirmed True
                                                      MsgBox(_img.InvokeRequired()) 'This is also true??
                                                      _img.Visible = False
                                                      DoOtherStuff()
                                                  End Sub)
End Function

这在其他地方一直有效。有什么不同会导致此错误?是否有某种原因导致我不应该在 OpenForms(0) 上调用?为什么 _img.InvokeRequired 在 Invoke 函数中为 true?

这是作为 Form.Load 事件的一部分在下载图像文件的任务内执行的。

埃德。添加 IsUIThread(),它检查主窗体是否需要在所有 UI 控件都在同一线程上的假设下调用:

Public Function IsUIThread() As Boolean
    If Application.OpenForms.Count = 0 Then Return Nothing
    Return Not Application.OpenForms(0).InvokeRequired
End Function

最佳答案

以下示例展示了如何编写扩展方法来执行您想要执行的操作:

Imports System.Runtime.CompilerServices

Public Module ControlExtensions

    <Extension>
    Public Sub InvokeIfRequired(source As Control, method As Action)
        If source.InvokeRequired Then
            source.Invoke(method)
        Else
            method()
        End If
    End Sub

End Module

然后你可以像这样使用它:

Public Sub ImgDisplayFromFile(img As PictureBox, imgFileName As String, Optional safe As Boolean = False)
    Dim _img = img

    If Not _img.IsDisposed Then _img.InvokeIfRequired(Sub()
                                                          _img.Visible = False
                                                          DoOtherStuff()
                                                      End Sub)
End Sub

关于.net - 在 Invoke() 内部运行时,跨线程操作对表单控件无效 - .NET,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76010581/

相关文章:

c# - BindingSource.Filter 不适用于 '!='

java - 如何在 JAVA 中的 Rijndael 加密等效项中获得正确的 KEY 和 IV

vb.net - 类不更新通过引用传递的变量

c# - Wcf服务操作契约变更

.net - 尝试在Azure管道上部署SQL数据库路径问题

.net - Npgsql 找不到带有 XML 参数的函数,而是寻找 TEXT

c# - 查看 Excel 是否处于 .NET 中的单元格编辑模式的解决方法

c++ - QEventLoop 用于同步等待信号

java - 在鼠标按下事件中启动 "asyncExec"会导致阻塞行为

c# - 如何恢复/中断 BackgroundWorker 线程