Bckground
我有一个用C#编写的网络应用程序。我的服务器程序有一个UI和几个通信线程,从tcp套接字读取并在控制器UI上显示消息。
通过单独的线程完成与每个客户端的通信。当我从一个客户端收到一些消息流时,该客户端的线程在UI上写入,这是一个表单上的richtextbox。
我调用表单的SetTextHelper(字符串文本)方法。
看起来像这样
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完全没有响应
- 调用解决了这个问题,但我读到了多线程环境,其中很多人共享相同的资源调用可能导致死锁我分享大约16个线程之间的共同ichtextbox
- 对我的情况有什么好处?
答案 0 :(得分:9)
您经常调用BeginInvoke()。 UI线程将在委托执行其正常职责之前调度委托,例如绘制控件和响应鼠标。如果委托目标正在做很多工作(将文本附加到RTB是昂贵的)或者你只是充满了请求,它就不再能够正常工作了。用户界面将冻结。这很容易发生,每秒大约1000个调用就足够了。
解决这个问题的关键是要意识到经常调用它是浪费精力。人眼无法以每秒25次的速度感知更新。因此缓冲文本直到自上次更新以来已经过了50毫秒。 Environment.TickCount是一个便宜的计时器。
还要注意,实际上生成文本的速度可能比附加到RTB的速度快。这需要限制线程。这很简单:使用Invoke而不是BeginInvoke。
答案 1 :(得分:3)
Invoke
不应导致死锁,除非您在进行调用时拥有锁定...但BeginInvoke
也不应使UI无响应。可能问题是你只是经常尝试更新文本框?也许缓冲传入的文本更多?例如,每半秒更新一次UI,而不是每次读取任何数据时都会更新。
答案 2 :(得分:2)
您可能只是花费所有时间设置文本。
尝试用普通RichTextBox
替换TextBox
;它应该快得多。