0

我有一个 winforms 应用程序,我需要在 Backgroundworker 线程内访问主窗体的 Handle 属性。

我创建了一个线程安全的方法,它使用 InvokeRequired 调用主窗体。我的问题是 - 为什么我仍然会收到“InvalidOperationException 跨线程操作无效”错误,即使像这样调用这个线程安全方法:

ProcessStartInfo psi = new ProcessStartInfo(file);
psi.ErrorDialogParentHandle = Utils.GetMainAppFormThreadSafe().Handle;

下面是线程安全方法的代码(我的主应用程序表单称为 Updater):

    /// <summary>
    /// delegate used to retrieve the main app form
    /// </summary>
    /// <returns></returns>
    private delegate Updater delegateGetMainForm();

    /// <summary>
    /// gets the mainform thread safe, to avoid cross-thread exception
    /// </summary>
    /// <returns></returns>
    public static Updater GetMainAppFormThreadSafe()
    {
        Updater updaterObj = null;
        if (GetMainAppForm().InvokeRequired)
        {
            delegateGetMainForm deleg = new delegateGetMainForm(GetMainAppForm);
            updaterObj = GetMainAppForm().Invoke(deleg) as Updater;
        }
        else
        {
            updaterObj = GetMainAppForm();
        }
        return updaterObj;
    }

    /// <summary>
    /// retrieves the main form of the application
    /// </summary>
    /// <returns></returns>
    public static Updater GetMainAppForm()
    {
        Updater mainForm = System.Windows.Forms.Application.OpenForms[Utils.AppName] as Updater;
        return mainForm;
    }

我做错了吗?先感谢您。

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

4

1 回答 1

1

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

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

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

更新:

此外,您需要GetMainAppFormHandleThreadSafe()代替GetMainAppFormThreadSafe()

public static IntPtr GetMainAppFormHandleThreadSafe()
{
    Form form = GetMainAppForm();
    if (form.InvokeRequired)
    {
        return (IntPtr)form.Invoke(new Func<IntPtr>(GetMainAppFormHandle));
    }
    else
    {
        return GetMainAppFormHandle();
    }
}
于 2011-08-14T08:45:20.557 回答