从另一个线程启动我的表单时,它无法正确显示

2023-12-04

情况是这样的: 我正在开发一个具有以下结构的简单应用程序:

  • FormMain(启动点)
  • 表单通知
  • 功能齐全

Right?

嗯,在FormMain我有以下功能:

private void DoItInNewThread(ParameterizedThreadStart pParameterizedThreadStart, object pParameters, ThreadPriority pThreadPriority)
{
    Thread oThread = new Thread(pParameterizedThreadStart);
    oThread.CurrentUICulture = Settings.Instance.Language;
    oThread.IsBackground = true;
    oThread.Priority = pThreadPriority;
    oThread.Name = "μRemote: Background operation";
    oThread.Start(pParameters);
}

所以,每次我需要调用位于复杂函数我执行以下操作:

// This is FormMain.cs
string strSomeParameter = "lala";
DoItInNewThread(new ParameterizedThreadStart(ComplexFunctions.DoSomething), strSomeParameter, ThreadPriority.Normal);

另一个类,FormNotification,它是一个向用户显示进程的一些信息的表单。 可以从 FormMain 或 ComplexFunctions 调用此 FormNotification。 例子:

// This is ComplexFunctions.cs
public void DoSomething(string pSomeParameter)
{
    // Imagine some time consuming task
    FormNotification formNotif = new FormNotification();
    formNotif.Notify();
}

FormNotify 有一个计时器,因此,10 秒后关闭表单。我没有使用 formNotif.ShowDialog 因为我不想将焦点放在这个表单上。 你可以检查一下这个链接看看我在通知中做了什么。

好的,问题是这样的: 当我打电话时表单通知 from 复函数这是从另一个线程中调用的FormMain... 这表单通知几毫秒后消失。 当你做这样的事情时,效果是一样的:

using(FormSomething formSomething = new FormSomething)
{
   formSomething.Show();
}

如何避免这种情况呢?

这些是我不想使用的可能解决方案:

  • 在 FormNotify 中使用 Thread.Sleep(10000)
  • 使用 FormNotif.ShowDialog()

这是一个简化的场景(FormNotify 做了一些其他花哨的事情,只停留 10 秒,但它们与查看问题无关)。

谢谢你的时间!!! 对不起我的英语。


几乎每个 GUI 库都被设计为只允许在为此目的指定的单个线程(称为 UI 线程)中进行更改 GUI 的调用。如果您在另一个线程中,则需要安排在 UI 线程中进行更改 GUI 的调用。在 .NET 中,执行此操作的方法是调用 Invoke(同步)或 BeginInvoke(异步)。等效的 Java Swing 调用是 invokeLater() ——几乎每个 GUI 库中都有类似的函数。

有一种东西叫做线程亲和力。 WinForm 应用程序中有两个线程,一个用于渲染,一个用于管理用户界面。您只处理用户界面线程。渲染线程保持隐藏状态 - 在后台运行。在 UI 线程上创建的唯一对象可以操作 UI - 即对象与 UI 线程具有线程关联性。

因为,您正在尝试从与 UI 线程不同的线程更新 UI(显示通知)。因此,在您的工作线程中定义一个委托并使 FormMain 监听此事件。在事件处理程序(在 FormMain 中定义)中编写代码以显示 FormNotify。

当您想要显示通知时,从工作线程触发事件。

当控件的创建线程以外的线程尝试访问该控件的方法或属性之一时,通常会导致不可预测的结果。常见的无效线程活动是对访问控件的 Handle 属性的错误线程的调用。将 CheckForIllegalCrossThreadCalls 设置为 true 可以在调试时更轻松地查找和诊断此线程活动。请注意,当应用程序在调试器外部启动时,非法跨线程调用始终会引发异常。

注意:将 CheckForIllegalCrossThreadCalls 设置为 ture 只能在调试情况下完成。不可预测的结果将会发生,并且您将最终尝试追踪您将很难找到的错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从另一个线程启动我的表单时,它无法正确显示 的相关文章

随机推荐

  • 如何以印地语语言以 unicode 形式存储数据

    我在用PHP and MySQL申请 问题是 如何将数据存储在MySQL 可读格式或 format 当用户在文本框中输入数据并单击提交时 我们会获得不同格式的数据 我们需要做什么来转换并存储在MySQL以可读的格式 选择utf8字符集并ut
  • 具有重复标签的ggplot轴自定义顺序

    set seed 357 x lt data frame name sample letters 10 val runif 10 stringsAsFactors F x c 2 6 name lt c k k ggplot x aes x
  • 主要 C/C++ 编译器生成的代码中的寄存器分配规则

    我记得以前 32 位 Intel 处理器之前 的一些规则 当时 至少对我来说 非常频繁地必须分析 C C 编译器 在我的例子中 当时是 Borland Turbo 生成的汇编输出查找性能瓶颈 并将汇编例程与 C C 代码安全地混合 诸如使用
  • 代码签名错误,如何将 Xcode 项目切换到另一台 Mac?

    我知道如何使用 Xcode 和一切 但这是一个初学者问题 我刚刚买了一台新的 MacBook Pro 我专门用它来开发 iPhone 我将主要应用程序项目从 Mac Mini 转移到了 MacBook Pro 这样我就可以在两台设备上工作
  • 如何重新启动一个线程

    我尝试编写一个文件监视器 如果附加了新行 它将检查文件 该监视器实际上是一个线程 它将始终通过随机访问文件读取该行 这是监控核心代码 public class Monitor public static Logger log Logger
  • 如何在 idl 中声明 IStream,以便 Visual Studio 将其映射到 s.w.interop.comtypes?

    我有一个 COM 对象 需要从 C 客户端获取流并对其进行处理 看来我应该使用 IStream 所以我像下面这样写我的idl 然后我使用 MIDL 编译为 tlb 编译我的解决方案 注册它 然后将对我的库的引用添加到 C 项目 Visual
  • C++ 字符串转二进制代码 / 二进制代码转字符串

    我需要将一个字符串转换为带有第一个字符串的二进制代码的字符串 对于第一部分 我使用了这个 将字符串转换为二进制的最快方法 工作完美 但我无法找到将其写入新字符串的方法 这是我到目前为止使用的代码 for size t i 0 i lt ou
  • Python循环遍历字符串并将其与通配符模式匹配

    string1 abc string2 abdabcdfg 我想知道 string1 是否是 string2 的子串 但是 也有通配符 例如 可以是任何字母 y can be a or d x can be b or c 因此 yx 将是子
  • SQL - WHERE 条件的顺序重要吗?

    假使 假设category id是表的索引键 不是主键 books 下面两条SQL语句有什么区别吗 SELECT FROM books WHERE author Bill AND category id 1 SELECT FROM book
  • 如何在 SymPy 中加速缓慢的矩阵乘法?

    我正在编写一个工具来使用 SymPy 求解特定的递推方程 并发现涉及矩阵乘法的步骤之一花费了非常长的时间 例如 如果我在 iPython 控制台中尝试以下操作 In 1 from sympy import In 2 A Matrix 500
  • 使用 ncurses pad 在 C 中滚动

    我试图在 ncurses 中获取一个窗口 在其中写入 mysql 查询的结果 但查询返回的行数比我终端中的行数多 所以我尝试创建一个垫子 以便我可以滚动浏览结果 但问题是 我的终端上没有可见的键盘 我只是简化了代码 但它仍然不适合我 inc
  • 完全合格的域名验证

    是否有一种快速而肮脏的方法来验证是否输入了正确的 FQDN 请记住 没有 DNS 服务器或互联网连接 因此必须通过 regex awk sed 完成验证 有任何想法吗 4 253 a zA Z0 9 1 63
  • CORS 错误,但仅在 POST 请求时出现,尽管有 cors 配置(GET 没有问题)

    我使用 Nodejs Express 服务器 尽管允许主机 但我仍然遇到 CORS 错误 请求中不存在 Access Control Allow Origin 标头 资源 但仅适用于 POST 端点 GET 没有问题 我的客户端浏览器允许使
  • 生成 PDF 时出现堆栈溢出异常 [重复]

    这个问题在这里已经有答案了 作为我的延续先前的问题我一直在尝试 PDF 的页眉和页脚功能 经过一番讨论后 我更改了 PdfPageEventHelper 类上的大量代码 以下是我所拥有的 public class ReportHeaderF
  • 将 VBA Range 复制粘贴到另一工作表 循环并转置数据

    对于 Excel 中的模型 我想将数据从工作簿中的一张工作表复制并粘贴到工作簿中的另一张工作表 并使用 for next 循环转置此数据 来自工作文件 CME 的数据应粘贴到 RME 工作文件中 数据总行数为2420 但是 由于复制和粘贴不
  • Android数据备份服务

    我正在尝试使用数据备份服务 以便保存用户共享首选项 如上所述here 然而 我在不同的Android版本中尝试测试时遇到了以下问题 安卓2 3 4 扩展 BackupAgentHelper 后 尝试使用 bmgr 工具测试服务 按照以下步骤
  • Rally 使用 Web 服务 API 批量添加测试用例结果

    我们即将开始通过 API 更新 Rally 测试结果的阶段 我找不到通过 Web 服务 API 执行此操作的示例 例如发布 xml 谁能指出我这一点吗 我还想知道有什么能力可以批量执行此操作 例如一次性上传一组测试结果 也许有连接器可以将各
  • Laravel 设置 cookie 不起作用

    我在自定义中间件中有以下代码 public function handle request Closure next if request gt hasCookie uuid return next request uuid 99 resp
  • 完全卸载并重新加载 Forge 查看器

    我在 Angular 5 应用程序上使用 Forge Viewer 有没有办法完全卸载查看器以便稍后重新加载 我有以下代码来卸载查看器 if this viewer this viewer running this viewer tearD
  • 从另一个线程启动我的表单时,它无法正确显示

    情况是这样的 我正在开发一个具有以下结构的简单应用程序 FormMain 启动点 表单通知 功能齐全 Right 嗯 在FormMain我有以下功能 private void DoItInNewThread ParameterizedThr