Обновление управления безопасностью потока C # - PullRequest
0 голосов
/ 02 ноября 2018

Вопрос : Когда форма и ее элементы управления доступны из потока, какой из них больше подходит?:

  1. вызов формы и обновление ее элементов управления в форме вызова

  2. отчетливо вызывает элементы управления и отчетливо обновляет элементы управления

Код

if (mainForm.InvokeRequired)
{
   mainForm.Invoke(
      (Action)(() =>
                  {
                     mainForm.label1.Text = "update";
                     mainForm.textBox1.Text = "update";
                     mainForm.button1.Text = "update";
                  }));
}
else
{
   mainForm.label1.Text = "update";
   mainForm.textBox1.Text = "update";
   mainForm.button1.Text = "update";
}


//OR

if (mainForm.label1.InvokeRequired)
{
   mainForm.Invoke((Action)(() => { mainForm.label1.Text = "update"; }));
}
else
{
   mainForm.label1.Text = "update";
}

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

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

 public void SafeExecute(IView form, Action methodToExecute)
 {
      // args chek....
      ISynchronizeInvoke view = form as ISynchronizeInvoke;
      if(view != null)
      {
        if (!View.InvokeRequired)
            {
                methodToExecute();
            }
            else
            {
                view.Invoke(methodToExecute, null);
            }
      }
      else methodToExecute();
 }

и затем в своем коде вы можете вызвать этот метод следующим образом (я предполагаю, что ваш взгляд реализует интерфейс, в данном случае я называю его IView)

 SafeExecute(this, () => {
   mainForm.label1.Text = "update";
   mainForm.textBox1.Text = "update";
   mainForm.button1.Text = "update";
 })
0 голосов
/ 02 ноября 2018

Каждый раз, когда вы Invoke, есть задержка и стоимость, так как мы должны отправить сообщение в поток пользовательского интерфейса, по сути, это сообщение «пожалуйста, запустите этот код». Затем мы должны подождать, пока поток пользовательского интерфейса заберет это сообщение (в настоящее время он может быть занят выполнением какой-то другой работы), выполнить код, который мы его просили, и показать, что это сделано. Затем, наконец, мы можем возобновить работу после вызова Invoke.

Теперь, по большому счету, эта стоимость довольно низкая. Так что, если вы просто используете Invoke один или два раза, это не стоит рассматривать. Однако, если вы планируете выполнить большой цикл и Invoke внутри цикла, вы можете сделать паузу и пересмотреть. Вместо этого лучше переместить Invoke за пределы цикла.

Однако поток пользовательского интерфейса является ценным ресурсом. Мы не хотим тратить время на этот поток, выполняя не задачи, связанные с пользовательским интерфейсом.

Так что, если у вас есть цикл, выполняющий смесь работы с интенсивным использованием процессора и обновлений пользовательского интерфейса, ни один из них не обязательно подходит. В таком случае, посмотрите, можете ли вы реструктурировать свой код так, чтобы вы готовили пакетов обновлений пользовательского интерфейса в цикле, а затем время от времени (или после цикла, если это возможно) выполняли Invoke, чтобы просто выполнить эти обновления пользовательского интерфейса.

В вашем случае, похоже, у вас уже есть пакет обновлений пользовательского интерфейса для выполнения. Поэтому предпочтите код, который Invoke один раз, чтобы сделать все три:

if (mainForm.InvokeRequired)
{
   mainForm.Invoke(
      (Action)(() =>
                  {
                     mainForm.label1.Text = "update";
                     mainForm.textBox1.Text = "update";
                     mainForm.button1.Text = "update";
                  }));
}
else
{
   mainForm.label1.Text = "update";
   mainForm.textBox1.Text = "update";
   mainForm.button1.Text = "update";
}

Но учтите, что обычно лучше структурировать код так, чтобы вы не дублировали фактических обновлений пользовательского интерфейса, которые у вас есть выше. Что-то вроде:

private void DoUpdate()
{
   if(mainForm.InvokeRequired)
   {
      mainForm.Invoke(DoUpdate);
      return;
   }
   mainForm.label1.Text = "update";
   mainForm.textBox1.Text = "update";
   mainForm.button1.Text = "update";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...