Что не так с моим многопоточным вызовом в Windows Forms?

Возникла проблема с приложением Windows Forms.

Форма должна отображаться из другого потока. Итак, в классе формы у меня есть следующий код:

private delegate void DisplayDialogCallback();

public void DisplayDialog()
{
    if (this.InvokeRequired)
    {
        this.Invoke(new DisplayDialogCallback(DisplayDialog));
    }
    else
    {
        this.ShowDialog();
    }
}

Теперь, каждый раз, когда я запускаю это, InvalidOperationException добавляется в строку this.ShowDialog();:

"Операция между потоками недопустима: элемент управления 'SampleForm' доступен из потока, отличного от потока, в котором он был создан."

Что не так с этим фрагментом кода? Разве это не допустимый способ сделать вызовы между потоками? Есть ли что-то особенное в ShowDialog()?

9 голосов | спросил Arseni Mourzenko 15 J0000006Europe/Moscow 2010, 18:43:52

5 ответов


0

Я считаю, что здесь происходит то, что этот код запускается до того, как Form когда-либо будет показан.

Когда в .Net создается Form, он не сразу получает сходство для определенного потока. Только когда выполняются определенные операции, такие как показ или захват ручки, он приобретает сходство. До того, как это произойдет, InvokeRequired будет трудно функционировать.

В данном конкретном случае сходство не установлено и родительский элемент управления не существует, поэтому InvokeRequired возвращает false, поскольку не может определить исходный поток ,

Способ исправить это - установить сходство с вашим элементом управления, когда он создается в потоке пользовательского интерфейса. Лучший способ сделать это - просто запросить у элемента управления его свойство handle.

var notUsed = control.Handle;
ответил JaredPar 15 J0000006Europe/Moscow 2010, 18:51:54
0

Скорее всего, вы получили этот код до того, как форма была показана, и поэтому дескриптор окна не был создан.

Вы можете добавить этот код перед вашим кодом, и все должно быть хорошо:

if (! this.IsHandleCreated)
   this.CreateHandle();

Изменить. Другая проблема в вашем коде. После отображения формы вы не можете снова вызывать ShowDialog (). Вы получите недопустимое исключение операции. Вы можете изменить этот метод, как предложили другие.

Возможно, вам лучше будет вызывать ShowDialog () напрямую из вызывающего класса и иметь другой метод для BringToFront () или что-то в этом роде ...

ответил Scott P 15 J0000006Europe/Moscow 2010, 19:14:22
0

Вы всегда можете попробовать протестировать другой элемент управления.

Например, вы можете получить доступ к коллекциям Application.Forms

public Control GetControlToInvokeAgainst()
{
    if(Application.Forms.Count > 0)
    {
        return Application.Forms[0];
    }
    return null;
}

Затем в вашем методе DisplayDialog () вызовите GetControlToInvokeAgainst () и проверьте на нулевое значение, прежде чем пытаться выполнить вызов invokerequired.

ответил Ben Cawley 15 J0000006Europe/Moscow 2010, 18:53:58
0

Скорее всего, дескриптор элемента управления еще не создан, и в этом случае Control.InvokeRequired возвращает false

Проверьте свойство Control.IsHandleCreated, чтобы убедиться, что это так.

ответил Willem van Rumpt 15 J0000006Europe/Moscow 2010, 18:54:04
0

Я также думаю, что SLaks это правильно. От MSDN .com /EN-US /библиотека /system.windows.forms.control.invokerequired.aspx ):

  

Если подходящего дескриптора не найдено, метод InvokeRequired возвращает значение false.

Если это возможно в вашем случае, я бы попытался объединить создание и отображение элемента управления в одном методе, т.е.

public DisplayDialog static Show()
{
  var result = new DisplayDialog; //possibly cache instance of the dialog if needed, but this could be tricky
  result.ShowDialog(); 
  return result;
}

вы можете вызвать шоу из другой ветки

ответил Grzenio 15 J0000006Europe/Moscow 2010, 18:56:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132