Вопрос по c++, vb.net, .net, c#, winforms – WinForms межпроцессная модификация

2

Всякий раз, когда я хочу изменить winform из другого потока, мне нужно использовать

->Invoke(delegate, params)

так что изменение происходит в собственном потоке winform.

Для каждой функции, которая нуждается в изменении графического интерфейса, мне нужна другая функция делегата.

Есть ли какая-то схема, которая позволяет мне ограничивать количество необходимых функций делегата? У меня есть класс контроллера, который обрабатывает весь графический интерфейс в одном месте, я думал о повторном использовании делегатов, но он плохо пахнет.

Я думаю, что мой вопрос может относиться ко всем языкам, где может работать winform

Какая версия .NET? John Saunders

Ваш Ответ

4   ответа
0

как выключил чеки и вручную проверил, что каждый звонок, который я использовал, был безопасным.

Удивительное число из них можно назвать перекрестными, потому что у меня была гарантия того, где находятся определенные потоки (семафоры), или потому, что они вызывали базовые функции API, которые могли использоваться в других процессах.

Я по-прежнему получал много вызовов, обычно на объектах контекста, чтобы я мог использовать MethodInvoker.

Я также столкнулся с неприятной ошибкой в Control.Invoke, заставившей меня написать собственную библиотеку invoker.

Закрытие элемента управления, ожидающего вызова, приводит к аварийному завершению гонки. Моя пользовательская версия будет вызываться правильно, пока поток-владелец все еще находится в цикле сообщений.
В чем была ошибка ... Я никогда не сталкивался с неприятным, но зная, как говорится, полдела, и, возможно, я избежал из-за невежества. :)
6

вы можете использовать лямбду, а в C # 2 - анонимных делегатов. Это упрощает синтаксис, когда нет необходимости повторно использовать поведение. Я всегда делаю синхронизацию в коде формы, а не в контроллере. Контроллер не должен быть обеспокоен этим видом «слесарного дела»; проблемы, которые более специфичны для технологии, чем для логики контроллера.

public void ResetFields()
{
    // use "delegate" instead of "() =>" if .Net version < 3.5
    InvokeOnFormThread(() => 
    {
        firstInput.Text = Defaults.FirstInput;
        secondInput.Text = Defaults.SecondInput;
        thirdChoice.SelectedIndex = Defaults.ThirdChoice;
    });
}

// change Action to MethodInvoker for .Net versions less than 3.5
private void InvokeOnFormThread(Action behavior) 
{
    if (IsHandleCreated && InvokeRequired)
    {
        Invoke(behavior);
    }
    else
    {
        behavior();
    }
}

Практически, сделайте все открытые методы в своей форме вызывающими & quot; InvokeOnFormThread. & Quot; В качестве альтернативы вы можете использовать AOP для перехвата открытых вызовов методов в вашей форме и вызова "InvokeOnFormThread" & quot; но вышеупомянутое сработало достаточно хорошо (если вы согласны и не забываете всегда делать это с помощью открытых методов в форме или UserControls).

1

как централизовать логику обновления формы GUI.

Что касается производительности (которой мы можем легко стать одержимыми) вызова многочисленных делегатов для синхронизации внешнего интерфейса, то некоторое время назад я написал программное обеспечение, которое превзошло эквивалентное C ++ (собственное) приложение Windows в плане синхронизации GUI! И это все благодаряBeginInvoke иThreadPool учебный класс.

С помощьюAction<> а такжеFunc<> делегаты иThreadPool класс тоже выгоден и считают общимInvoke образец (выставленный Майклом выше):

public void TheGuiInvokeMethod(Control source, string text)
{
   if (InvokeRequired)
      Invoke(new Action<Control, string>(TheGuiInvokeMethod, source, text);
   else
   {
       // it is safe to update the GUI using the control
      control.Text = text;
   }
}

гдеTheGuiInvokeMethod будет действительно находиться в форме или другом элементе управления.

2

System.Action<T> а такжеSystem.Func<T,T> делегаты:

control.Invoke(
    new Action<int, string>(
        (i, s) => MessageBox.Show(String.Format(s, i))), 1, "{0}");
int iret = (int) control.Invoke(new Func<int, int>(i1 => i1 + 1));
Печально, но эти делегаты недоступны в .net 2. Однако их можно легко объявить самостоятельно.
Увидетьmsdn.microsoft.com/en-us/library/018hxwa8.aspx, 2.0 и выше.

Похожие вопросы