ShowDialog с использованием invoke делает приложение не отвечает - PullRequest
0 голосов
/ 18 июля 2011

Я использую Control.Invoke(), чтобы показать диалог. Код является обработчиком для получения учетных данных от пользователя и может выполняться в потоке, поэтому я выполняю вызов во InvokeRequired/Invoke фрагмент.

Иногда, и только на некоторых машинах, когда я закрываю диалог, приложение перестает отвечать на запросы (оно не управляет одними щелчками мыши, но управляет другими). Если я выполняю некоторые «разрешенные» действия, приложение снова начинает реагировать. Похоже, что обрабатывая любое событие, приложение исправляет себя.

Знаете ли вы какую-либо известную ошибку в .NET Framework или что-то, что могло вызвать эту проблему?

Заранее спасибо.


РЕДАКТИРОВАТЬ : это код, который я использую:

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

Ответы [ 2 ]

1 голос
/ 18 июля 2011

Действительно ли необходим Control.Invoke в этом случае?

У меня всегда было впечатление, что invoke использовался для обеспечения доступа к элементам пользовательского интерфейса потоком, который создает элемент управления, который обычно является потоком пользовательского интерфейса, но не должен быть.

В этом случае похоже, что вы пытаетесь создать диалог из потока, и, следовательно, вы должны иметь возможность обновить его из потока. (Очевидно, что вы не можете получить к нему доступ снаружи вашего потока, который будет включать основной поток пользовательского интерфейса).

Если я ошибаюсь, без сомнения, это очень быстро понизится.

0 голосов
/ 18 июля 2011

mParentControl всегда будет установлен равным parentControl, даже если его NULL не выглядит правильным.

Причина, по которой ваша программа перестает отвечать на запросы, заключается в том, что ваш mParentControl имеет значение NULL:

DialogResult result = dialog.ShowDialog(mParentControl);

OneРешение этой проблемы состоит в том, чтобы показать диалог, только если родитель известен.

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

Я основал свой ответ на следующем коде:

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

Я думаю, вы имеете в виду, что мой ответ не имеет смысла.Что имеет больше смысла, что комментарий Ханса Пассанта не содержит правды, или ваш код на самом деле правильный, и вы обнаружили ошибку.Поскольку вы грубите, я просто воспользуюсь своим опытом и помогу кому-нибудь еще.Забавляйся сам и добавь код, чтобы избежать mParentControl - это пустая ситуация, потому что ЭТО МОЖЕТ БЫТЬ.mParentControl ВСЕГДА установлен на parentcontrol, даже когда его NULL.

Верхняя форма приложения./// Может быть нулем, если неизвестно

...