C # Делегат вызвал необходимый вопрос - PullRequest
0 голосов
/ 12 апреля 2010

Сценарий

У меня есть приложение на C # Windows для создания форм, в котором есть несколько процессов. Эти процессы выполняются в отдельных потоках, и все они возвращаются в класс Main Form с обновлениями окна журнала и индикатора выполнения. Я использую следующий код ниже, который до сих пор работал нормально, однако у меня есть несколько вопросов.

код

     delegate void SetTextCallback(string mxID, string text);
     public void UpdateLog(string mxID, string text)
     {
         if (txtOutput.InvokeRequired)
         {
            SetTextCallback d = new SetTextCallback(UpdateLog);
            this.BeginInvoke(d, new object[] { mxID, text });
         }
         else
         {
            UpdateProgressBar(text);
         }
     } 

Вопрос

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

Время от времени я получаю исключения из OutofMemory, и программа всегда кажется, что происходит сбой вокруг этого куска кода ......

Ответы [ 3 ]

2 голосов
/ 12 апреля 2010

Да, для этого кода технически возможно вызвать OOM. Это произойдет, когда поток пользовательского интерфейса не сможет угнаться за рабочим потоком. Каждый Control.BeginInvoke () добавляет делегата к внутреннему List<Delegate>, поддерживаемому Windows Forms. Насос сообщений очищает этот список. Если он не успевает за скоростью, с которой рабочий поток вызывает BeginInvoke, тогда список увеличивается без границ и, в конце концов, вызывает OOM.

Если действительно вызывается только 10 раз в секунду и код только обновляет индикатор выполнения и , то поток пользовательского интерфейса в противном случае простаивает, тогда OOM не должен бывает. То, что это происходит, говорит о том, что вы как-то называете этот метод lot чаще, чем 10 раз в секунду. Или реальный код делает гораздо больше, чем просто обновление PB, как предполагает название «UpdateLog». Использование Invoke вместо BeginInvoke решает эту проблему, но замедляет работу.

1 голос
/ 12 апреля 2010

Этот код в порядке, причина исключений где-то еще в программе. Вы можете оптимизировать это, вызывая UpdateProgressBar напрямую или через BeginInvoke вместо вызова UpdateLog.

    delegate void SetTextCallback(string text);

     public void UpdateLog(string mxID, string text)
     {
         if (txtOutput.InvokeRequired)
         {
            SetTextCallback d = new SetTextCallback(UpdateProgressBar);
            this.BeginInvoke(d, new object[] { text });
         }
         else
         {
            UpdateProgressBar(text);
         }
     } 

Но я полагаю, что есть что-то еще, что не показано в этом посте.

1 голос
/ 12 апреля 2010

BeginInvoke возвращает IAsyncResult, который игнорируется в вашем коде. Просто используйте вместо этого Invoke.

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