Как правильно решить проблемы с многопоточностью в приложении systray? - PullRequest
3 голосов
/ 14 июля 2011

Итак, я недавно приобрел существующее приложение WinForms.Нам нужно изменить его на что-то, что запускается в системном трее, но все равно выскакивает форму, когда пользователь хочет.Нет проблем.Согласно этому вопросу: Mutex используется для обеспечения работы только одной копии приложения

Приложение имеет 3 основных компонента: пользовательский контекст приложения (myContext), который обрабатывает всю системушальные вещи.myContext создает экземпляр класса с именем Gozer (myGozer).Гозер делает всю настоящую работу.Он выполняет серию операций с определенным интервалом времени (проверяет состояние сети, если у нас есть соединение, он делает несколько других вещей. Он также играет в «Глобальную термоядерную войну» с собой).Это даст всем остальным знать, что происходит через серию событий.Когда myForm открывается, myContext передает myGozer внутрь.

Когда я открываю myForm, я начинаю сталкиваться со всеми видами проблем перекрестного потока (каждый раз, когда используется какой-либо элемент управления. Например, манипулирование myListView).То, что я не понимаю, это лучший способ справиться с этим.Я очень мало знаю о потоках.У меня нет очень большого мозга, который может понять, что такое потоки за 30 секунд.И у меня нет никого вокруг, кого я могу есть, чтобы поглотить их превосходное знание потоков.

Согласно этому вопросу , я могу просто проверить someControl.InvokeRequired изатем вызовите метод через делегата.Это работает.Но теперь я сталкиваюсь с тем, чтобы бросать кучу кода перед каждым разом, когда мне нужно иметь дело с элементом управления, который запускает несколько плохо откалиброванных тревожных звонков в моей голове.Я также обнаружил проблему при выходе из приложения;это вызывает еще одно исключение Cross-Threading обратно в myContext.Я не уверен, что уместно выходить из приложения из myForm, но какое еще безумное ожидание ожидает меня в это время?Я чувствую, что настраиваюсь на множество побочных эффектов, вызванных побочными эффектами.

Я думаю, я действительно беспокоюсь о том, чтобы создать кучу потенциальных проблем в будущем.Или попросить расширить возможности Gozer, а затем создать дополнительные проблемы, когда это требует работы в myForm.Или обнаружение, что открытие и закрытие myForm во время работы создает кучу дополнительных проблем с многопоточностью.Или что приложение заставит все взорваться.

Есть ли что-то еще, что я должен рассмотреть или пропустить?

Примечание: это для приложения .net 2.0, поэтому решение Jethro не будет работатьВот.Тем не менее, поскольку это не , то во многих местах мне приходится писать логику InvokeRequired, я просто собираюсь это сделать.Я почти уверен, что в следующем году мне удастся обновить его до .net 3.5, и ниже предлагается класс, в котором я расскажу о его проблеме.В результате я отмечаю это как ответ.

Ответы [ 2 ]

4 голосов
/ 15 июля 2011

Когда вы делаете обновление, есть альтернатива, если вы не хотите писать метод расширения.Вы должны быть удобны с синтаксисом лямбда, хотя.Вот пример:

myTextBox.Invoke( (Action) (() => myTextBox.Text = "text goes here"));

Я обычно не проверяю, требуется ли вызов, и просто выполняю вызов (вы обычно знаете, обновляете ли вы другой поток, а не поток пользовательского интерфейса).

ПРИМЕЧАНИЕ. Раньше у меня был похожий метод расширения, но я устал создавать его во всех моих проектах или создавать в библиотеке, которую нужно было добавить во все мои проекты.Это «простой» однострочный способ сделать это.

О, и если вам нужно выполнить несколько операций, вы также можете сделать это встроенным образом так:

myListView.Invoke( (Action) (() => 
    {
        myListView.Columns.Add("Column 1", -2, HorizontalAlignment.Left);
        myListView.Columns.Add("Column 2", -2, HorizontalAlignment.Left);
        myListView.Columns.Add("Column 3", -2, HorizontalAlignment.Left);
        myListView.Columns.Add("Column 4", -2, HorizontalAlignment.Center);
    }));
3 голосов
/ 14 июля 2011

Вот расширение, которое вы можете использовать. Не могу вспомнить, где я его взял.

Назовите это так.

this.InvokeEx(p=> p.txtbox.Text = "Rad");


public static class ControlExtensions
{
    public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                                Func<TControl, TResult> func)
        where TControl : Control
    {
        return control.InvokeRequired
                ? (TResult)control.Invoke(func, control)
                : func(control);
    }

    public static void InvokeEx<TControl>(this TControl control,
                                            Action<TControl> func)
        where TControl : Control
    {
        control.InvokeEx(c => { func(c); return c; });
    }

    public static void InvokeEx<TControl>(this TControl control, Action action)
        where TControl : Control
    {
        control.InvokeEx(c => action());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...