0

Control.Invoke()用来显示一个对话框。该代码是从用户那里获取凭据的处理程序,它可以在线程中执行,这就是我将调用执行到InvokeRequired/Invoke片段中的原因。

有时,并且仅在某些机器上,当我关闭对话框时,应用程序变得无响应(它不管理某些鼠标点击,但管理其他点击)。如果我执行一些“允许”的操作,应用程序将再次开始响应。似乎处理任何事件,应用程序都会自行修复。

您是否知道 .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

2 回答 2

1

在这种情况下是否真的需要 Control.Invoke?

我一直认为调用用于确保创建控件的线程访问 UI 元素,该线程通常是 UI 线程,但并非必须如此。

在这种情况下,您似乎正在尝试从线程创建对话框,因此您应该能够从线程更新它。(显然你不能从你的线程之外访问它,这将包括主 UI 线程)。

如果我错了,毫无疑问,这将很快被否决。

于 2011-07-18T14:14:04.423 回答
0

mParentControl 将始终设置为等于 parentControl,即使它的 NULL 看起来不正确。

您的程序变得无响应的原因是因为您的 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 is Null 情况,因为它可以发生。mParentControl 始终设置为 parentcontrol,即使它为 NULL。

申请表。/// 如果未知,可以为空

于 2011-07-18T17:37:47.413 回答