Работая над существующим проектом, я должен использовать WinForms (не работая с ним некоторое время), и у вас возникла проблема синхронизации с потоком пользовательского интерфейса.
Дизайн, который мне нужно интегрировать с работами следующим образом: A BackgroundWorker
получает Action
в качестве параметра и выполняет его асинхронно. Действие, над которым я работаю, состоит из двух частей; базовый класс (содержащий бизнес-логику) и часть GUI, которая уведомляется ядром через события, если требуется запросить взаимодействие с пользователем.
Я добавил создание дескриптора в конструктор формы
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
? И как мне избежать этого? - Почему
form.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; }
}