0

私はwinformsアプリを持っており、Backgroundworkerスレッド内のメインフォームのHandleプロパティにアクセスする必要があります。

InvokeRequiredを使用してメインフォームを呼び出すスレッドセーフなメソッドを作成しました。私の質問は、次のようにこのスレッドセーフメソッドを呼び出した場合でも、「InvalidOperationExceptionクロススレッド操作が無効です」というエラーが発生するのはなぜですか。

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

そして、以下はスレッドセーフメソッドのコードです(私のメインのアプリフォームはアップデーターと呼ばれています):

    /// <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;
    }

私はsmthを間違っていますか?前もって感謝します。

後で編集:最初にハンドルが必要な理由を投稿します。おそらく別の解決策/アプローチがあります。私のBackgroundworkerスレッドでは、ループ内に複数のプログラムをインストールする必要があり、インストーラーごとにプロセスを開始します。ただし、この操作が管理者だけでなく標準ユーザーでも機能するように、昇格を要求する必要があります。要するに、私はここのチュートリアルに従おうとしています

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 に答える