2011-07-18 50 views
0

我使用Control.Invoke()來顯示一個對話框。該代碼是一個處理程序,用於從用戶獲取憑證,並且可以在一個線程中執行,這就是我將該呼叫執行爲InvokeRequired/Invoke代碼段的原因。使用invoke的ShowDialog正在使應用程序無響應

有時候,只有在某些機器中,當我關閉對話框時,應用程序變得無法保留(它不管理一些鼠標點擊,但管理其他)。如果我執行一些「允許」操作,應用程序將再次啓動。看起來處理任何事件,應用程序都會修復它自己。

您是否知道.NET框架中的任何已知錯誤,或者是否會導致此問題?

在此先感謝。


編輯:這是我使用的代碼:

public class GuiCredentialsHandler 
{ 
    // control used to invoke if needed 
    private static Control mInvokeControl; 

    // control used as parent for showDialog (could be null) 
    private static Control mParentControl; 

    /// <summary> 
    /// Initialize a GetCredentials handler for current process. 
    /// This method should be always called from the UI thread, for 
    /// a correctly handling for invokes (when the handler is called 
    /// from a thread). 
    /// </summary> 
    /// <param name="parentControl">Application top form. 
    /// Can be null if unknown</param> 
    public static void Initialize(Control parentControl) 
    { 
     if (parentControl != null) 
     { 
      mInvokeControl = parentControl; 
     } 
     else 
     { 
      mInvokeControl = new Control(); 
      // force to create window handle 
      // otherwise, invoke required always 
      // return false 
      mInvokeControl.CreateControl(); 
     } 

     mParentControl = parentControl; 
    } 

    public static Credentials GetCredentials(
     string servername, SEIDWorkingMode serverWorkingMode) 
    { 
     if (mInvokeControl.InvokeRequired) 
     { 
      return mInvokeControl.Invoke(
       new GetCredentialsDelegate(DoGetCredentials), 
       new object[] { servername, serverWorkingMode }) 
      as Credentials; 
     } 
     else 
     { 
      return DoGetCredentials(servername, serverWorkingMode); 
     } 
    } 

    private static Credentials DoGetCredentials(
     string servername, SEIDWorkingMode serverWorkingMode) 
    { 

     GetCredentialsDialog dialog = new GetCredentialsDialog(); 

     dialog.Server = servername; 
     dialog.WorkingMode = serverWorkingMode; 

     DialogResult result = dialog.ShowDialog(mParentControl); 

     if (result == DialogResult.Cancel) return null; 

     UserInfoRetriever retriever = new UserInfoRetriever(
      servername, serverWorkingMode, 
      dialog.UserName, dialog.Password); 

     SEID seid = retriever.GetCurrentUser(); 

     return new Credentials(seid, serverWorkingMode); 
} 

public delegate Credentials GetCredentialsDelegate(
    string serverName, 
    SEIDWorkingMode mode); 
+4

這不可能是它的一個bug。我會發布你的代碼。還請描述哪些操作起作用並且不起作用。 –

+0

@Rhhound:我發佈了源代碼。謝謝。 –

+0

@Daniel你的GetCredentials有一個嘗試沒有抓住。 – LarsTech

回答

1

是Control.Invoke確實需要在這種情況下?

我總是覺得調用被用來確保線程訪問UI元素,創建的控件通常是UI線程,但不一定是。

在這種情況下,它看起來像你試圖從一個線程創建一個對話框,因此你應該能夠從線程更新它。 (顯然你不能從你的線程之外訪問它,這將包括主UI線程)。

如果我錯了,毫無疑問,這將很快得到降低。

+0

我在showDialog中使用父窗體(mParentControl)作爲IWin32Owner。我需要調用,否則我會得到一個InvalidOperationException異常(跨線程訪問)。 –

+0

對不起 - 錯過了ShowDialog(mParentControl)位。 – sgmoore

0

mParentControl將始終設置爲等於parentControl,即使其NULL看起來不正確。

程序變得unresposive的原因是因爲你的mParentControl是NULL:解決此問題

DialogResult result = dialog.ShowDialog(mParentControl); 

一種解決方案是,只顯示該對話框如果父母是已知的。

if (mParentControl != NULL) 
    DialogResult result = dialog.ShowDialog(mParentControl); 
else 
    DialogResult result = dialog.ShowDialog(mInvokeControl); 

我根據我對下面的代碼答案:

if (parentControl != null) 
       { 
        mInvokeControl = parentControl;     
       }  

我想你的意思是我的答案是沒有意義的。更有意義的是,Hans Passant的評論並不具備某些事實,或者你的代碼實際上是正確的,並且你發現了一個錯誤。既然你不禮貌,我只會把我的經驗和幫助別人。幽默自己,並添加代碼,以避免mParentControl是空情況,因爲它可以發生。 mParentControl總是設置爲parentcontrol,即使其爲NULL。

申請表格。 ///可以爲空如果 未知

+0

你錯了。如果我傳遞一個空的parentControl,mInvokeControl是一個新的Control(),mParentControl是null。否則,如果我將有效的控件傳遞給Initialize()方法,則mParentControl和mInvokeControl將具有相同的引用。我需要管理這兩種情況。現在,我正在測試第二種情況,我將一個控件傳遞給Initialize()方法,所以mParentControl不會爲null。 –

+0

@DanielPeñalba - 你甚至試過我的代碼嗎?技術上你所擁有的也是有缺陷的。 –

+0

對不起,但你的答案沒有意義。 mParentControl不是NULL。我正在通過我的應用程序mainform來初始化。在這種情況下,mInvokeControl和mParentControl是同一個對象。請檢查代碼。 –

相關問題