2011-08-14 8 views
0

私はwinformsアプリケーションを持っていて、Backgroundworkerスレッド内のメインフォームのHandleプロパティにアクセスする必要があります。backgroundworkerスレッド内でwindowsフォームに正しくアクセスする

私は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; 
    } 

私は間違っているのですか? ありがとうございます。

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

答えて

1

あなたはスレッドセーフな方法でハンドルを取得していません。代わりに、スレッドセーフな方法でFormインスタンスを取得し、安全でない方法でHandleプロパティにアクセスします。

あなたが直接ハンドルを返すメソッドGetMainAppFormHandle()を追加して、スレッドセーフな方法で、その1つの呼び出す必要があります:あなたはGetMainAppFormHandleThreadSafe()代わりのGetMainAppFormThreadSafe()を必要とするほか

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(); 
    } 
} 
+0

私はこれを試しましたが、IntPtrがControl objではないことに気づきました私はこの静的メソッドをスレッドセーフな方法で呼び出すことができるように、InvokeRequiredやInvokeのようなプロパティはありません。 –

+0

私はあなたのコードが最初に思ったよりも壊れていることに気づきました。つまり、同じメソッドをスレッドセーフな方法で呼び出す必要があるかどうかを判断するために、安全でない方法で 'GetMainAppForm()'を呼び出します。それは意味をなさない。とにかく、私は私の答えを更新し、より多くのコードを含んでいます。 – Codo

+0

コメントをいただきありがとうございます - 私のコードには意味をなさない部分があります:GetMainAppForm()。InvokeRequired、またはupdaterObj = GetMainAppForm()。Updater(Invoke)を呼び出しますか? –

関連する問題