我遇到了一些我不知道如何解释的行为。当我反复绘制到 aSystem.Windows.Forms.Form
时不注意不要挂线程,几秒钟后,绘图输出冻结,我在标题中
看到可怕的(不响应)文本:
此屏幕截图不是中画;它正在绘制的图像在程序结束时完全是红色的,但绘图在中途停止了。奇怪的是,如果我Form.Text
在绘制之前跳过设置属性,它不会冻结。谁能解释为什么?
我正在使用循环来绘制一些多线程图形填充算法的进度,但看到屏幕输出冻结。因为我是在画图然后Thread.Sleep()
循环调用,所以我应该预料到这种行为(其他帖子指出我可能应该使用BackgroundWorker
,但只是使用Application.DoEvents()
停止了我的冻结)。
但是,当我删除代码以找到我的错误时,真正让我惊讶的是,当我删除对 change 的调用时form.Text
,它不再冻结了!它也没有调用执行任何操作的 setter;分配给空字符串 ( form.Text = "";
) 也会导致它不冻结。因此,由于某种原因,当Text
为空时,Windows 并不关心程序是否响应,并且会愉快地继续显示绘图进度!到底是怎么回事?Windows 是否以不同的方式处理带有空标题的程序?
我将代码减少到看到冻结所需的最低限度。当程序运行时,表单图像将被循环填充为红色。大约填充到一半时它就会停止,即使循环继续运行!您会看到,在它完成后,它会处理事件并再绘制一次以显示整个图像是红色的,然后再停留两秒钟。
(如果您在调试 (F5) 的情况下运行,它不会冻结;您必须在不调试的情况下运行 (Ctrl-F5)。这使得弄清楚这一切变得更加困难!)
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
// Include resources System.Drawing, System.Windows.Forms in VS before compiling
class Program
{
static void Main(string[] args) {
Bitmap image = new Bitmap(400, 20);
Form form = new Form();
form.Text = "some title"; // Comment this out to avoid the freeze
form.SetBounds(30, 30, image.Width + 16, image.Height + 38);
form.Show();
Graphics graphics = Graphics.FromHwnd(form.Handle);
for (int x = 0; x < 400; ++x)
for (int y = 0; y < 20; ++y) {
image.SetPixel(x, y, Color.Red);
graphics.DrawImage(image, 0, 0);
Thread.Sleep(1);
// Calling this would prevent the freeze:
//Application.DoEvents();
}
Application.DoEvents();
graphics.DrawImage(image, 0, 0);
Thread.Sleep(2000);
}
}