国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C# 一個簡單的秒表引發的窗體卡死問題

2019-11-17 03:06:27
字體:
來源:轉載
供稿:網友

C# 一個簡單的秒表引發的窗體卡死問題

一個秒表程序也是我的一個心病,因為一直想寫這樣的一個東西,但是總往GUI那邊想,所以就比較怵,可能是上學的時候學MFC搞出的后遺癥吧,不過當我今天想好用Win Form(話說還是第一次寫win form)寫這么一個東西的時候,居然so easy。

所以說,做不了不可怕,怕的是你不去做,因為你不去做,你就永遠不知道你能不能做它。事實證明,大部分你猶豫能不能做的事情,實際上你都能搞定。

雖然成功實現了一個秒表的簡單功能,即開始計時和停止。但是卻引發了一個關于win form和C#線程的問題。

下面一個一個來,先說一下秒表的類實現

namespace Utils{    public class Time    {        PRivate int _minute;        private int _second;        private bool _flag;//線程標識        private Thread _TimingThread = null;        public Time()        {            this._minute = 0;            this._second = 0;            this._flag = true;        }        /// <summary>        /// 開始計時        /// </summary>        public void Start()        {            if (_TimingThread == null)            {                _TimingThread = new Thread(new ThreadStart(AddSecond));                _TimingThread.Start();            }        }        /// <summary>        /// 線程執行方法        /// </summary>        private void AddSecond()        {            while(_flag)            {                Thread.Sleep(1000);                if (this._second == 59)                {                    this._minute++;                    this._second = 0;                }                else                {                    this._second++;                }            }        }        /// <summary>        /// 格式化顯示計時結果        /// </summary>        /// <returns></returns>        public string FormatTimeResult()        {            string minute = string.Empty;            string second = string.Empty;            if (this._minute < 10)            {                minute = "0" + this._minute.ToString();            }            else             {                minute = this._minute.ToString();            }            if (this._second < 10)            {                second = "0" + this._second.ToString();            }            else            {                second = this._second.ToString();            }            return minute + ":" + second;        }        /// <summary>        /// 停止        /// </summary>        public void Stop()        {            this._flag = false;        }        /// <summary>        /// 歸0操作        /// </summary>        public void Zero()        {            this._minute = 0;            this._second = 0;        }    }}

秒表的實現還是比較簡單的,感覺這樣寫,也方便以后做擴展。

下面說說win form方面

窗體就是這樣,一個label,兩個button

QQ圖片20140613105209

最開始,我寫了這樣一段代碼

    public partial class Form1 : Form    {        private Time mTime = null;        private Thread mDisplayThread = null;        public Form1()        {            InitializeComponent();            mTime = new Time();//實例化秒表類        }        private void button_start_Click(object sender, EventArgs e)        {            mTime.Start();            mDisplayThread = new Thread(new ThreadStart(DisplayCurrentTime));            mDisplayThread.Start();            button_start.Enabled = false;        }        public void DisplayCurrentTime()        {            while (true)            {                Thread.Sleep(1000);                label_Time.Text = mTime.FormatTimeResult();//對Label標簽進行實時更新                Console.WriteLine("{0}", mTime.FormatTimeResult());            }        }        private void button_stop_Click(object sender, EventArgs e)        {            mTime.Stop();            button_start.Enabled = true;        }}

這樣寫感覺思路上沒什么問題,當點擊【開始計時】按鈕的同時創建一個線程,而這個線程是用來每隔一秒去更新一下label上的顯示計時時間。

然而,之后卻報一個這樣的錯誤:Cross-thread Operation not valid: Control 'label_Time' accessed from a thread other than the thread it was created on.

網上查了一下,這個錯誤貌似很常見,MSDN上也給了一個出現此錯誤的原因,是這樣說的,當您試圖從單獨的線程更新一個win form時,會出現這個錯誤。

查了一下,就是說win form上的控件屬性想要進行修改的時候,只能在創建Control的線程里調用,不能在以外的線程被調用。而上面的

label_Time.Text = mTime.FormatTimeResult();

這段代碼呢恰恰是發生在新創建的線程之中,所以就會報錯了。

解決辦法是用delegate(委托)加上control.Invoke去聯合實現。下面看看實現部分

    public partial class Form1 : Form    {        private Time mTime = null;        private Thread mDisplayThread = null;        public delegate void UpdateLabel();//聲明一個委托        public UpdateLabel updateLabel;//定義一個委托        public Form1()        {            InitializeComponent();            mTime = new Time();            updateLabel = new UpdateLabel(UpdateTime);//實例化一個委托對象        }        private void button_start_Click(object sender, EventArgs e)        {            mTime.Start();            mDisplayThread = new Thread(new ThreadStart(DisplayTimeFunc));            mDisplayThread.Start();            button_start.Enabled = false;        }        /// <summary>        /// 線程執行方法        /// </summary>        public void DisplayTimeFunc()        {            while (true)            {                Thread.Sleep(1000);                this.Invoke(this.updateLabel);            }        }        /// <summary>        /// 單獨對Label進行刷新        /// </summary>        public void UpdateTime()        {            label_Time.Text = mTime.FormatTimeResult();        }        private void button_stop_Click(object sender, EventArgs e)        {            mTime.Stop();            button_start.Enabled = true;        }    }

這段代碼里mDisplayThread線程執行了DisplayTimeFunc方法,而DisplayTimeFunc方法里實際就是在更新label,不同的是使用了Control.Invoke方法,上面不是說對控件屬性的更改要在創建控件的線程里才執行嗎?現在看起來好像還是老樣子。那是因為我們不了解Control.Inv

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 梁河县| 大同市| 桃园市| 临西县| 万安县| 商南县| 遂川县| 舞钢市| 营山县| 阿图什市| 兴城市| 宜宾市| 莱西市| 台东县| 松滋市| 崇义县| 慈溪市| 太保市| 巴林右旗| 广德县| 上饶市| 攀枝花市| 甘洛县| 肇州县| 宿迁市| 湄潭县| 句容市| 安福县| 林甸县| 秦皇岛市| 宁国市| 卢龙县| 呼图壁县| 江山市| 建宁县| 淄博市| 蓝田县| 广昌县| 吴川市| 太保市| 加查县|