Синхронизация рабочего с потоком пользовательского интерфейса

Работая над существующим проектом, я должен использовать WinForms (какое-то время не работал с ним), и у меня проблема с синхронизацией с пользовательским интерфейсом. нить.

Дизайн, с которым мне нужно интегрироваться, работает следующим образом: A BackgroundWorker получает Action в качестве параметра и выполняет его асинхронно. Действие, над которым я работаю, состоит из двух частей; базовый класс (содержащий бизнес-логику) и часть графического интерфейса, уведомляемая ядром посредством событий, если ему необходимо запрашивать взаимодействие с пользователем.

Я добавил создание дескриптора в конструктор формы

if (!IsHandleCreated)
{
    //be sure to create the handle in the constructor
    //to allow synchronization with th GUI thread
    //when using Show() or ShowDialog()
    CreateHandle();
}

При этом работает следующий код:

private DialogResult ShowDialog(Form form)
{
    DialogResult dialogResult = DialogResult.None;
    Action action = delegate { dialogResult = form.ShowDialog(); };
    form.Invoke(action);
    return dialogResult;
}

В этом примере в качестве места запуска было задано значение по умолчанию для Windows.

Если я изменю его на:

Action action = delegate { dialogResult = form.ShowDialog(ParentWindow); };

Где ParentWindow - это экземпляр IWin32Window , а для WindowStartupLocation установлено значение CenterParent . Я получаю исключение между потоками при вызове form.Invoke (action) .

Межпоточная операция недействительна: элемент управления ActivationConfirmationForm доступен из потока, отличного от потока, в котором он был создан.

Вопросы:

  • Почему возникает исключение между потоками только при установке местоположения запуска как CenterParent ? И как мне этого избежать?
  • Почему форма.InvokeRequired всегда false ?

Оба, вероятно, связаны!?

[править] @Reniuz: Вы здесь ничего не упускаете;) Вызов осуществляется слушателем, уведомляемым ядром

private static void OnActivationConfirmationRequired(DmsPackageConfiguratorCore sender,
ConfigurationActivationConfirmationEventArgs args)
{
    args.DoAbort = (ShowDialog(new ActivationConfirmationForm(args.Data)) == DialogResult.No);
}

Все, что в моем распоряжении, находится в графическом интерфейсе

/// <summary>
/// Interface defining methods and properties used to show dialogs while performing package specific operations
/// </summary>
public interface IPackageConfiguratorGui
{
/// <summary>
/// Gets or sets the package configurator core.
/// </summary>
/// <value>The package configurator core.</value>
IPackageConfiguratorCore PackageConfiguratorCore { get; set; }

/// <summary>
/// Gets or sets the parent window.
/// </summary>
/// <value>The parent window.</value>
IWin32Window ParentWindow { get; set; }

/// <summary>
/// Gets the package identifier.
/// </summary>
/// <value>The package identifier.</value>
PackageIdentifier PackageIdentifier { get; }
}
10
задан Philippe 26 January 2012 в 13:34
поделиться