Не отвечает интерфейс при использовании BeginInvoke - PullRequest
1 голос
/ 24 марта 2010

Bckground
У меня есть сетевое приложение, написанное на C #. моя серверная программа имеет пользовательский интерфейс и несколько потоков связи, которые читают из сокетов tcp и отображают сообщения на пользовательском интерфейсе контроллера.

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

Я вызываю метод SetTextHelper (string text) формы.

, который выглядит так

private delegate void MyTextUpdateHandler(string text);
public void SetTextHelper(string text)
{
   BeginInvoke(new MyTextUpdateHandler(SetText), new object[] { text });
}

public setText(string text)
{
   richtext.Text+= text;
}

Вопрос
- Если я использую BeginInvoke, мой пользовательский интерфейс полностью не отвечает, когда я пишу большой поток данных в пользовательский интерфейс - Invoke решает эту проблему, но я читал, что для многопоточной среды, где многие хосты совместно используют один и тот же ресурс, Invoke может привести к взаимоблокировкам. Я разделяю общую таблицу ichtextbox между 16 потоками - Что было бы хорошим дизайном для моей ситуации?

Ответы [ 3 ]

9 голосов
/ 24 марта 2010

Вы слишком часто вызываете BeginInvoke (). Поток пользовательского интерфейса отправит делегат, прежде чем он выполнит свои обычные обязанности, такие как рисование элементов управления и реагирование на мышь. Если цель делегата выполняет большую работу (добавление текста в RTB стоит дорого), или вы просто заполняете его запросами, он больше не может выполнять свою обычную работу. Пользовательский интерфейс будет зависать. Это происходит довольно легко, достаточно 1000 вызовов в секунду.

Ключом к решению этой проблемы является осознание того, что это столь бесполезная попытка вызывать так часто. Человеческий глаз не может воспринимать обновления быстрее, чем 25 раз в секунду. Так что буферизуйте текст, пока не прошло 50 миллисекунд с момента последнего обновления. Environment.TickCount - дешевый таймер.

Также имейте в виду, что на самом деле вы можете создавать текст быстрее, чем его можно добавить в RTB. Это требует регулирования потока. Это просто: используйте Invoke вместо BeginInvoke.

3 голосов
/ 24 марта 2010

Invoke не должно приводить к взаимоблокировкам, если только вы не владеете блокировкой, пока выполняете вызов ... но BeginInvoke также не должно приводить к тому, что пользовательский интерфейс также не отвечает. Может быть проблема в том, что вы просто пытаетесь обновить текстовое поле слишком часто? Возможно, буфер входящего текста больше? Например, обновляйте пользовательский интерфейс только каждые полсекунды, а не каждый раз, когда вы читаете какие-либо данные.

2 голосов
/ 24 марта 2010

Вы, вероятно, просто тратите все свое время на установку текста.

Попробуйте заменить RichTextBox на обычный TextBox; это должно быть намного быстрее.

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