2011-08-14 77 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()。调用(委托)作为更新? –

相关问题