2017-05-18 61 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

相關問題