【发布时间】:2017-10-26 08:47:51
【问题描述】:
我有两个用户控件,它们在我的 winforms 项目中添加到一个表单中,一个具有绘制字符串并使其从右向左滚动的功能,另一个绘制另一个字符串并使其从下到上滚动并且通过在 while(true) 循环内调用 Invalidate() 再次控制。但是当我的字符串之一变得太长时,大约 1000 个字符的 UI 线程被阻塞,所以我的问题是:我做错了什么?有没有更好的方法让文本滚动??? 下面是我的sn-p代码:
int scrollTextSpeed = 100;
bool scrollingText = true;
Thread updateUI ;
void init(){
updateUI = new Thread(updateScrollText);
updateUI.Start();
}
void updateScrollText()
{
while (true)
{
if (scrollingText) {
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal,
new MethodInvoker(Invalidate));
Thread.Sleep(scrollTextSpeed);
}
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
SizeF stringSize = e.Graphics.MeasureString(text, this.Font);
var yPos = (this.ClientSize.Height / 2) - (stringSize.Height / 2);
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
e.Graphics.DrawString(text, this.Font, brus,
currentPos, yPos);
if (fisttime)
{
currentPos = this.ClientSize.Width - 1;
fisttime = false;
}
else
{
if (currentPos < (-1 * (stringSize.Width)))
currentPos = this.ClientSize.Width - 1;
else
currentPos -= scrollPixelDistance;
}
}
【问题讨论】:
-
不要在繁忙的循环中失效。无关紧要。计时器存在。如果字符串没有变化,那么每次测量字符串也没有意义。也不要每次都画,因为你可以把它保存为位图
-
为什么要画文字?为什么不使用
Label? -
我将您的代码复制粘贴到一个新的 WinForms 项目中,并使其编译 - 它一直滚动 50000 个字符的字符串,并且表单仍然响应用户输入。
-
另外,想想如果
scrollingText变成false,您的while (true)循环会发生什么...(不是这会导致您的问题,但会导致其他问题。)跨度> -
很难猜测 Dispatcher.CurrentDispatcher 是如何在 Winforms 应用程序中结束的。这是不正确的,它不知道哪个线程是正确的 UI 线程。死锁当然并不罕见。请改用 Control.BeginInvoke()。您需要一个 Form 对象,如果您很绝望,请使用 Application.OpenForms[0]。请注意滚动速度,如果 UI 线程跟不上,那么它就会开始消耗 100% 内核,这看起来也像是“冻结”。
标签: c# multithreading winforms