环境:
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.csnamespace 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;
    }
}

解决方案 »

  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);            }        }
    也不会有任何问题,神奇了,求解答。
      

  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?
      

  4.   

    摘录msdn内容:
    访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。 你既然在以不安全地方式操作控件,怎么能要求它要“正常”工作呢?并不仅仅是visible属性,其他很多属性很多方法都可能出现各种各样你想得到想不到的问题