gpt4 book ai didi

c# - 在没有 WinForm 控件的情况下在主线程上调用一个方法来调用 Invoke 或 BeginInvoke

转载 作者:太空狗 更新时间:2023-10-29 22:34:50 26 4
gpt4 key购买 nike

我想在后台线程上运行一个操作。当它完成后,我想检查发生的任何错误并将它们重新扔到我的原始线程上。

我正在使用后台 worker 。在 RunWorkerCompleted 事件处理程序中抛出异常会导致未处理的异常 - 如果事件处理程序在后台线程上运行,这是有意义的。如果我有一个 winform 控件,我可以调用 Invoke 或 BeginInvoke,但我在这个对象中没有 winform 控件,尽管它是一个 winform 项目。

如何重新抛出后台工作程序中发生的异常?

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// I want to throw an exception here, without causing an unhandled exception and without being able to call Invoke or BeginInvoke on a WinForm control.
}
else if (e.Cancelled)
{
// Do something useful
}
else
{
if (e.Result != null)
{
// Do something with the result
}
}
}

我会假设 RunWorkerCompleted 事件处理程序将在原始调用线程上运行。在这种情况下,也许后台 worker 不是我所需要的。

最佳答案

无法将代码注入(inject)到另一个正在运行的线程中。甚至操作系统也做不到这一点。

Control.BeginInvoke 的工作方式是将委托(delegate)引用放入队列中,然后使用 PostMessage 将用户消息发布到 UI 线程的消息队列中。 Application.Run 消息循环查找此消息,并在找到时将委托(delegate)从队列中弹出并执行。

要点是,如果不对主线程进行编码以从其他线程寻找某种信号(或消息),则没有其他方法可以完成您需要的操作。

已添加

您声明这是一个 WinForm 应用程序,但您没有可用于使用 BeginInvoke 的控件。

编辑:我没有仔细考虑就建议延迟加载。控件最终可能会在错误的线程上创建

Application.Run 之前预先创建一个在应用程序的整个生命周期内都存在的控件。您可以将其用于 BeginInvoke from。

编辑 #3

然后我尝试这样做以确保它有效,当然它无效。您不能简单地创建一个通用控件,它必须有一个 HWND 句柄。简单修复:像这样创建它:

invokerControl = new Control();
invokerControl.CreateControl();

这将允许您从中调用 BeginInvoke,即使没有打开的 Form 对象可以调用。

关于c# - 在没有 WinForm 控件的情况下在主线程上调用一个方法来调用 Invoke 或 BeginInvoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3494068/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com