VS2010, .net 4.0
准备工作:
1,初始化时将控件的visible属性置为false,或者在form的构造函数中将控件的visible属性置为false
2,允许直接在线程中修改控件,在form的构造函数中添加如下代码: Control.CheckForIllegalCrossThreadCalls = false;
现象描述:
在线程中将控件的visible属性置为true,则程序死机.
相关调研:
1,将控件的visible初始化属性改为true,则在线程中可以动态改变控件的visible属性,不会有任何问题.
2,通过button点击,或者用timer触发来改变控件的visible属性也不会有任何问题.
求大神解答:
初始化时将控件的visible属性置为false,为什么就不能再在线程中动态改变visible属性?
以下是代码
form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public bool mVal = true;
// static Int32 ii = 0;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
Thread tmp = new Thread(setvis);
tmp.Start();
}
private void button1_Click(object sender, EventArgs e)
{
mVal = true;
// label1.Visible = mVal;
}
private void button2_Click(object sender, EventArgs e)
{
mVal = false;
// label1.Visible = mVal;
}
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
Thread.Sleep(100);
label1.Visible = mVal;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
//label1.Visible = !label1.Visible;
}
}
}
form1.designer.cs
namespace WindowsFormsApplication1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(48, 41);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(65, 12);
this.label1.TabIndex = 0;
this.label1.Text = "sadasdfsaf";
this.label1.Visible = false;
//
// button1
//
this.button1.Location = new System.Drawing.Point(191, 66);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(191, 111);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 2;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Timer timer1;
}
}
4 个解决方案
#1
上述代码,将form1.designer.cs中的代码:“this.label1.Visible = false;”删除,则不会有任何问题。
或者将form1.cs中的代码
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
Thread.Sleep(100);
label1.Visible = mVal;
}
}
修改为
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
label1.Visible = mVal;// mVal初始化为true,先设置为true,再睡眠
Thread.Sleep(100);
}
}
也不会有任何问题,神奇了,求解答。
或者将form1.cs中的代码
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
Thread.Sleep(100);
label1.Visible = mVal;
}
}
修改为
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
label1.Visible = mVal;// mVal初始化为true,先设置为true,再睡眠
Thread.Sleep(100);
}
}
也不会有任何问题,神奇了,求解答。
#2
线程中修改主界面的东西,必须使用委托。
第一种:
private delegate void CustomAction();
使用:
this.FindForm().Invoke(new CustomAction(delegate()
{
//代码
}));
第二种:
private delegate void CustomAction();
void Method()
{
if(!this.InvokeRequired)
{
//代码
}
else
{
this.BeginInvoke(new CustomAction(Method));
}
}
如果带参数则加上参数即可。
#3
使用委托肯定没问题。
就是不知道为什么控件的visible属性会对初始化值有要求。难道是MS的BUG?
就是不知道为什么控件的visible属性会对初始化值有要求。难道是MS的BUG?
#4
摘录msdn内容:
访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。
你既然在以不安全地方式操作控件,怎么能要求它要“正常”工作呢?
并不仅仅是visible属性,其他很多属性很多方法都可能出现各种各样你想得到想不到的问题
访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。
你既然在以不安全地方式操作控件,怎么能要求它要“正常”工作呢?
并不仅仅是visible属性,其他很多属性很多方法都可能出现各种各样你想得到想不到的问题
#1
上述代码,将form1.designer.cs中的代码:“this.label1.Visible = false;”删除,则不会有任何问题。
或者将form1.cs中的代码
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
Thread.Sleep(100);
label1.Visible = mVal;
}
}
修改为
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
label1.Visible = mVal;// mVal初始化为true,先设置为true,再睡眠
Thread.Sleep(100);
}
}
也不会有任何问题,神奇了,求解答。
或者将form1.cs中的代码
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
Thread.Sleep(100);
label1.Visible = mVal;
}
}
修改为
private void setvis()
{
while (true)
{
// ii++;
// label1.Text = ii.ToString();
label1.Visible = mVal;// mVal初始化为true,先设置为true,再睡眠
Thread.Sleep(100);
}
}
也不会有任何问题,神奇了,求解答。
#2
线程中修改主界面的东西,必须使用委托。
第一种:
private delegate void CustomAction();
使用:
this.FindForm().Invoke(new CustomAction(delegate()
{
//代码
}));
第二种:
private delegate void CustomAction();
void Method()
{
if(!this.InvokeRequired)
{
//代码
}
else
{
this.BeginInvoke(new CustomAction(Method));
}
}
如果带参数则加上参数即可。
#3
使用委托肯定没问题。
就是不知道为什么控件的visible属性会对初始化值有要求。难道是MS的BUG?
就是不知道为什么控件的visible属性会对初始化值有要求。难道是MS的BUG?
#4
摘录msdn内容:
访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。
你既然在以不安全地方式操作控件,怎么能要求它要“正常”工作呢?
并不仅仅是visible属性,其他很多属性很多方法都可能出现各种各样你想得到想不到的问题
访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。
你既然在以不安全地方式操作控件,怎么能要求它要“正常”工作呢?
并不仅仅是visible属性,其他很多属性很多方法都可能出现各种各样你想得到想不到的问题