2010-03-24 77 views
1

背景
我有用C#编写的网络应用程序。我的服务器程序有一个UI和几个通信线程,它们从tcp套接字读取并在控制器UI上显示消息。使用BeginInvoke时无响应的UI

与每个客户端的通信是通过一个分离线程完成的。当我从一个客户端接收到一些消息流时,该客户端的线程在UI上写入,这是一个Form上的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我的UI是,当我写的大量数据流UI 完全反应迟钝 - 调用解决了这个问题,但我读了对于多线程环境,其中有许多共享资源共享相同的资源Invoke可能导致死锁我在大约16个线程之间共享公共的ichtextbox - 对我的情况来说,什么是好的设计?

回答

3

Invoke不应该导致死锁,除非你在调用时拥有一个锁......但是BeginInvoke也不应该使UI失效。问题是你只是想经常更新文本框?也许缓冲传入的文本更多?例如,每半秒更新一次UI,而不是每次读取任何数据时。

+0

请注意,他不是追加。 – SLaks 2010-03-24 19:38:21

+0

@SLaks:尽管他可以在调用SetTextHelper的代码中追加。目前基本上还不清楚UI为什么没有响应,但我怀疑它只是超载了数据。 – 2010-03-24 19:39:21

+0

是的,我将数据附加到richtextbox。但我很困惑为什么Invoke使它正常工作,而BeginInvoke不是?每次添加到富文本框中的文本都很小,但大约有64个字符 – Kazoom 2010-03-24 21:10:37

2

你可能只是花时间设置文本。

尝试用普通的TextBox代替RichTextBox;它应该快得多。

9

您经常调用BeginInvoke()。 UI线程会在代理执行其正常工作之前调度委托,如绘制控件和响应鼠标。如果委托对象正在做很多工作(向RTB附加文本的代价很高),或者您只是将请求填充到其中,否则就不会继续执行其正常工作。 UI将冻结。这很容易发生,大约每秒1000次调用就足够了。

解决这个问题的关键是要认识到,这是经常被浪费的努力。人眼无法以每秒25次的速度感知更新。因此,缓冲文本直到自上次更新以来已过50毫秒。 Environment.TickCount是一个便宜的计时器。

另外要注意,实际上您可能会生成的文本比可以附加到RTB更快。这需要限制线程。这很简单:使用Invoke而不是BeginInvoke。

+0

好吧,我会尽力做到这一点,但为什么我不应该得到与BeginInvoke无反应,而不是调用? – Kazoom 2010-03-24 21:18:42

+0

有趣的事情要注意,TickCount以毫秒为单位 - 不在蜱中(他们在想什么?) – 2010-11-26 00:01:26

+0

这个名字是在20世纪80年代后期选择的。当时时钟慢点。 – 2012-11-01 19:30:00