Winforms 在backgroundworker线程内正确访问windows窗体

Winforms 在backgroundworker线程内正确访问windows窗体,winforms,thread-safety,backgroundworker,invokerequired,Winforms,Thread Safety,Backgroundworker,Invokerequired,我有一个winforms应用程序,需要访问Backgroundworker线程中主窗体的句柄属性 我制作了一个线程安全的方法,用invokererequired调用主窗体。我的问题是-为什么即使像这样调用此线程安全方法,我仍然会出现“InvalidOperationException cross thread operation not valid”错误: ProcessStartInfo psi = new ProcessStartInfo(file); psi.ErrorDialogPare

我有一个winforms应用程序,需要访问Backgroundworker线程中主窗体的句柄属性

我制作了一个线程安全的方法,用invokererequired调用主窗体。我的问题是-为什么即使像这样调用此线程安全方法,我仍然会出现“InvalidOperationException cross thread operation not valid”错误:

ProcessStartInfo psi = new ProcessStartInfo(file);
psi.ErrorDialogParentHandle = Utils.GetMainAppFormThreadSafe().Handle;
下面是线程安全方法的代码(我的主要应用程序表单称为Updater):

//
///用于检索主应用程序窗体的委托
/// 
/// 
私有委托更新程序delegateGetMainForm();
/// 
///获取mainform线程安全,以避免跨线程异常
/// 
/// 
公共静态更新程序GetMainAppFormThreadSafe()
{
Updater updaterObj=null;
if(GetMainAppForm().InvokeRequired)
{
delegateGetMainForm deleg=新的delegateGetMainForm(GetMainAppForm);
updaterObj=GetMainAppForm()。作为更新程序调用(deleg);
}
其他的
{
updaterObj=GetMainAppForm();
}
返回updaterObj;
}
/// 
///检索应用程序的主窗体
/// 
/// 
公共静态更新程序GetMainAppForm()
{
Updater mainForm=System.Windows.Forms.Application.OpenForms[Utils.AppName]作为更新程序;
返回主窗体;
}
我做错了吗? 先谢谢你


稍后编辑:我将首先发布我需要句柄的原因,也许还有另一种解决方案/方法。在Backgroundworker线程中,我需要在一个循环中安装多个程序,并为每个安装程序启动一个进程。但是,我需要请求提升,以便此操作也可以用于标准用户,而不仅仅是管理员。简言之,我试图按照教程进行操作

您没有以线程安全的方式获得句柄。相反,您以线程安全的方式获取
表单
实例,然后以不安全的方式访问
句柄
属性

您应该添加一个方法
GetMainAppFormHandle()
,该方法直接返回句柄并以线程安全的方式调用该句柄:

public static IntPtr GetMainAppFormHandle()
{
    return System.Windows.Forms.Application.OpenForms[Utils.AppName].Handle;
}
更新:

此外,您需要
GetMainAppFormHandleThreadSafe()
而不是
GetMainAppFormThreadSafe()

public static IntPtr GetMainAppFormHandleThreadSafe()
{
Form Form=GetMainAppForm();
如果(需要调用表单)
{
return(IntPtr)form.Invoke(newfunc(GetMainAppFormHandle));
}
其他的
{
返回GetMainAppFormHandle();
}
}

我刚刚尝试了这个方法,但意识到IntPtr不是一个控制对象,因此没有像invokererequired或Invoke这样的属性,因此我可以以线程安全的方式调用这个静态方法。我刚刚意识到您的代码比我最初想象的更糟:您调用
GetMainAppForm()
以不安全的方式,只是为了确定是否需要以线程安全的方式调用相同的方法。这毫无意义。无论如何,我已经更新了我的答案并包含了更多的代码。谢谢你的评论-你的意思是没有意义的部分在我的代码中:GetMainAppForm().InvokeRequired,或者updaterObj=GetMainAppForm().Invoke(deleg)as Updater?两者都有。您最初的假设是必须以线程安全的方式调用
GetMainAppForm()
。然而,在调用
Invoke
之前,您以一种不安全的方式调用了它两次,其核心是线程安全的方式。但是,在其他地方需要线程安全访问,即在使用
Handle
属性时。
public static IntPtr GetMainAppFormHandle()
{
    return System.Windows.Forms.Application.OpenForms[Utils.AppName].Handle;
}
public static IntPtr GetMainAppFormHandleThreadSafe()
{
    Form form = GetMainAppForm();
    if (form.InvokeRequired)
    {
        return (IntPtr)form.Invoke(new Func<IntPtr>(GetMainAppFormHandle));
    }
    else
    {
        return GetMainAppFormHandle();
    }
}