使用调用的 ShowDialog 使应用程序无响应

发布于 2024-11-24 22:56:52 字数 2663 浏览 1 评论 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);

I'm using Control.Invoke() to show a dialog. The code is a handler to get credentials from the user and it can be execute in a thread, this is the reason I perform the call into an InvokeRequired/Invoke snippet.

Sometimes, and only in some machines, when I close the dialog, the application becomes unresposive (it does not manage some mouse clicks, but manage others). If I execute some "allowed" actions, the application start to be responsive again. It seems that processing any event, the application fixes itself.

Do you know any known bug in the .NET framework, or something that could cause this issue?

Thanks in advance.


EDIT: This is the code I'm using:

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

违心° 2024-12-01 22:56:52

在这种情况下确实需要 Control.Invoke 吗?

我一直有这样的印象:调用用于确保 UI 元素由创建控件的线程访问,该线程通常是 UI 线程,但不一定是。

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

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

Is Control.Invoke actually needed in this case?

I was always under the impression that invoke was used to ensure that UI elements are accessed by the thread that creates the control which is usually the UI thread but does not have to be.

In this case it looks like you are trying to create a dialog from a thread and hence you should be able to update it from the thread. (Obviously you can't access it from outside your thread, which will include the main UI thread).

If I'm wrong no doubt this will get downvoted very quickly.

罪歌 2024-12-01 22:56:52

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 为 Null 的情况,因为它可能会发生。 mParentControl 始终设置为parentcontrol,即使其为NULL。

申请顶部表格。 /// 可以为 null 如果
未知

mParentControl will always be set equal to parentControl even if its NULL which does not seem right.

The reason your program becomes unresposive is because your mParentControl is NULL:

DialogResult result = dialog.ShowDialog(mParentControl);

One solution around this problem is to only show the dialog if the parent is known.

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

I based my answer on the following code:

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

I think you mean my answer makes no sense. What makes more sense that Hans Passant comment doesn't hold some truth or your code is actually correct and you discovered a bug. Since you are being rude I will just take my experience and help somebody else. Humor yourself and add code to avoid the mParentControl is Null situation because IT CAN HAPPEN. mParentControl is ALWAYS set to parentcontrol even when its NULL.

Application top form. /// Can be null if
unknown

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文