2017-05-18 64 views
0

我想关闭一个窗体窗体,当前有一个外部线程的焦点。问题是,我无法通过简单地调用form.Focused来按照预期的方式访问该属性,它引发“InvalidOperationException:跨线程操作无效”。接下来,我尝试调用它的Invoke,但它无法识别Control.Focused作为getter方法。下面是当前的代码:如何从另一个线程调用窗体属性值?

private void CloseFormWithFocus() 
{ 
    FormCollection openForms = Application.OpenForms; 
    Form closeThisForm = null; 

    foreach (Form f in openForms) 
    { 
     // Here's the part that does not compile 
     if (closeThisForm.Invoke((MethodInvoker)delegate() { closeThisForm.Focused; });) 
     { 
      closeThisForm = f; 
     } 
    } 
} 

然而是什么让我困惑的是,另一种方法是比较给form.Name财产关闭形式几乎相同的方法可以让我简单地这样称呼它(可能不是线程安全的):

private void CloseForm(string formName) 
{ 
    FormCollection openForms = Application.OpenForms; 
    Form closeThisForm = null; 

    foreach (Form f in openForms) 
    { 
     if (f.Name == formName) 
     { 
      closeThisForm = f;      
     } 
    } 
} 

我已经找过各种不同的方法来调用属性getter,但所有来源只是声明编译器应该识别调用窗体。将焦点作为getter,现在我很难过。

如果form.Propertyname调用不起作用,那么调用(或只是简单地读取,如果可能的话)从外部线程的窗体的属性值的正确方法是什么?

谢谢。

+0

委托类型错误,您需要'Func '。但这不是真正的问题,因为它是一个基本的线程比赛错误,所以你也不能使用Application.OpenForms。你需要在UI线程上运行整个方法。在调用此方法的代码中使用BeginInvoke()。 –

+0

@HansPassant注意,谢谢。大概可以在以后节省我的头痛。 – NikeTheSword

回答

0

Focused属性不是“只是一个吸气剂”。

它将当前聚焦窗口与控件的Handle属性进行比较。 Handle属性首先检查跨线程访问。
从源代码:

public virtual bool Focused { 
     get { 
      return IsHandleCreated && UnsafeNativeMethods.GetFocus() == Handle; 
     } 
    } 

public IntPtr Handle { 
     get { 
      if (checkForIllegalCrossThreadCalls && 
       !inCrossThreadSafeCall && 
       InvokeRequired) { 
       throw new InvalidOperationException(SR.GetString(SR.IllegalCrossThreadCall, 
                   Name)); 
      } 

您可以从Invoke返回值是这样的:

f.Invoke(new Func<bool>(() => f.Focused)) 

注意:您使用closeThisForm(而其空),而不是f

相关问题