(У этого вопроса есть немного истории, пожалуйста, потерпите меня)
В этом вопросе я говорил о возможности централизации фокус-покуса '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. Я могу представить, что может возникнуть проблема, если я попытаюсь обновить элемент управления, который еще не обработан (но в этом случае я все равно прикручен ).