標籤:style blog http os io strong for ar
概要Windows Forms 控制項通常不是thread-safe(直接或間接繼承於System.Windows.Forms.Control),因此.NET Framework為防止multithread下對控制項的存取可能導致控制項狀態的不一致,在調試時,CLR-Debugger會拋出一個InvalidOperationException以‘建議‘程式員程式可能存在的風險。 問題的關鍵在於,動機是什嗎?和由此而來的編程模型的調整。
1. Example首先,看一個代碼執行個體。該例要完成的工作是由一個Button的Click觸發,啟動一個Thread(Manual Thread),該Thread的目的是完成設定TextBox的Text’s Property。
1.1 Unsafe access to control
Code 1.1using System;using System.Configuration;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Threading;using System.IO; namespace WindowsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void unsafeSetTextButton_Click(object sender, EventArgs e) { Thread setTextThread = new Thread(new ThreadStart(doWork)); setTextThread.Start(); } private void doWork() { string fileName = ".\\test-src.txt"; if (!File.Exists(fileName)) { MessageBox.Show(string.Format("{0} doesn‘t exist!", fileName), "FileNoFoundException"); return; } string text = null; using (StreamReader reader = new StreamReader(fileName, Encoding.Default)) { text = reader.ReadToEnd(); }
this.textBox1.Text = text; } }} 在調試時,CLR-Debugger會在以上代碼中粗體處將會彈出如下的對話方塊: 提示說,當前存取控制項的thread非建立控制項的thread(Main Thread)。
1.2 What’s mean?當然,你也可以忽略InvalidOperationException,在非調試的狀態下,該異常並不會被拋出,CLR-Debugger監測對Handle的可能存在的不一致地存取,而期望達到更穩健(robust)的代碼,這也就是Cross-thread operation not valid後的真正動機。 但是,放在面前的選擇有二:第一,在某些情況下,我們並不需要這種善意的‘建議‘,而這種建議將在調試時帶來了不必要的麻煩;第二,順應善意的‘建議‘,這也意味著我們必須調整已往行之有效且得心應手的編程模型(成本之一),而這種調整額外還會帶來side-effect,而這種side-effect目前,我並不知道有什麼簡潔優雅的解決之道予以消除(成本之二)。
2. The first choice : CheckForIllegalCrossThreadCalls忽略Cross-thread InvalidOperationException建議,前提假設是我們不需要類似的建議,同時也不想給自己的調試帶來過多的麻煩。 關閉CheckForIllegalCrossThreadCalls,這是Control class上的一個static property,預設值為flase,目的在於開關是否對Handle的可能存在的不一致存取的監測;且該項設定是具有Application scope的。 如果,只需要在某些Form中消除Cross-thread InvalidOperationException建議,可以在Form的.ctor中,InitializeComponent語句後將CheckForIllegalCrossThreadCalls設定為false 。
Code 2. - 1public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = false;}