2011-08-14 24 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()直接返回的句柄,並調用一個在一個線程安全的方式:

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

我剛試過這個,但意識到IntPtr不是控制對象因此沒有像InvokeRequired或Invoke這樣的屬性,因此我可以以線程安全的方式調用此靜態方法。 –

+0

我剛剛意識到你的代碼比我第一次想到的更糟糕:你以不安全的方式調用'GetMainAppForm()'來確定是否需要以一種線程安全的方式調用相同的方法。這是沒有意義的。無論如何,我已經更新了我的答案幷包含更多代碼。 – Codo

+0

感謝您的評論 - 你的意思是沒有任何意義的部分在我的代碼中:GetMainAppForm()。InvokeRequired或updaterObj = GetMainAppForm()。調用(委託)作爲更新? –

相關問題