我在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’从创建它的线程以外的线程访问."

在下面的代码中,on_img.Visible=False失败.我之前暂停了执行,以确认它正在UI线程中运行.该变量引用了我在设计器中创建的PictureBox,因此它显然也应该在UI线程中.(我还确认函数not位于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会为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相关问答推荐

为什么Linq中的运算符逻辑不匹配结果,当值为0或在VB. NET中没有

无法在Ubuntu 22.04.3上运行带有Rider 2023和DotNet-8.0的项目

关于在 .NET 中干净地终止线程的问题

将 DataRowCollection 转换为 IEnumerable

有什么方法可以使用 .NET 应用程序使用 git 吗?

防止对话框在按钮的单击事件处理程序中关闭

如何在 WPF 应用程序中使用 App.config 文件?

为什么 C# 多维数组不实现 IEnumerable

你如何调试 MVC 4 API 路由?

WCF反序列化如何在不调用构造函数的情况下实例化对象?

如何比较 C# 中的(目录)路径?

.Net 正则表达式:单词字符 \w 是什么?

如何仅在需要时提升权限?

错误 NU1605 检测到包降级

绑定到不在列表中的值的可编辑组合框

DLL 中有什么以及它是如何工作的?

如何从 WCF REST 方法返回自定义 HTTP 状态代码?

IronPython 与 Python .NET

如何将 MailMessage 对象作为 *.eml 或 *.msg 文件保存到磁盘

LINQ 可以与 IEnumerable 一起使用吗?