Сохранение глобальной ссылки на элемент управления в WinForms для доступа к потоку GUI - PullRequest
2 голосов
/ 15 февраля 2010

(У этого вопроса есть немного истории, пожалуйста, потерпите меня)

В этом вопросе я говорил о возможности централизации фокус-покуса 'cross thread', который требуется для обновления GUI, вот так:

//Utility to avoid boiler-plate InvokeRequired code
//Usage: SafeInvoker.Invoke(myCtrl, () => myCtrl.Enabled = false);
public static void Invoke(Control ctrl, Action cmd)
{
    if (ctrl.InvokeRequired)
        ctrl.BeginInvoke(new MethodInvoker(cmd));
    else
        cmd();
}

На прошлой неделе, обдумывая тот факт, что это всегда происходит (в моем коде) при обработке события, и отчасти вдохновленный методом расширения событий Дастин Кэмпбелл , я подготовил это:

//Utility to avoid boiler-plate SafeInvoker.Invoke code
//Usage obj.EventRaised += obj_EventRaised.OnGUIThread(controlreference);
public static EventHandler OnGUIThread(this EventHandler h, Control ctrl)
{
    // lambda expressions are not syntactic sugar, they are syntactic crack!
    return (s, e) => SafeInvoker.Invoke(ctrl, () => h(s, e));
}

То, что меня здесь раздражает, - это всегда иметь под рукой контроль. Насколько я знаю, есть только один поток с графическим интерфейсом, поэтому здесь можно использовать любой элемент управления.

Мне стало интересно, как создать синглтон GUIContext и выдать ему ссылку на мою основную форму при запуске приложения, а затем получить доступ к ней из моего метода расширения, исключив тем самым необходимость в параметре ctrl.

Это плохая идея, и если да, то почему? Есть ли лучший способ сделать это? Я знаю, что в Rx есть понятие Context, но я не знаю ничего эквивалентного в ванильных WinForms. Я могу представить, что может возникнуть проблема, если я попытаюсь обновить элемент управления, который еще не обработан (но в этом случае я все равно прикручен ).

Ответы [ 2 ]

1 голос
/ 15 февраля 2010

Выполнение этого ограничит вас одной основной формой и одним потоком GUI. Но потребность в главном потоке графического интерфейса - такое же требование форм .NET (и базового Win32 API), как и все остальное, поэтому вряд ли это изменится.

Вы бы знали, изменится ли наличие единой главной формы для вашего приложения или нет. Даже если бы это было так, ваш синглтон был бы лучшим местом для отслеживания того, какая форма является «основной», чем для передачи его всем фоновым потокам.

В целом, для меня это выглядит разумно. Я использовал глобальную переменную для хранения hwndMain в своих неуправляемых приложениях более десяти лет и никогда не сожалел об этом.

1 голос
/ 15 февраля 2010

Я подозреваю, что во многих случаях SynchronizationContext.Current может делать многое из того, что вы хотите здесь (будьте осторожны - это также может быть null). Но только Send или Post к этому.

Если вы делаете сохраняете глобальный объект - возможно, напечатаете его так же, как ISynchronizeInvoke - меньше вероятность непреднамеренного злоупотребления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...