1. CheckForIllegalCrossThreadCalls属性
在新建的线程为控件属性CheckForIllegalCrossThreadCalls设置值false
CheckForIllegalCrossThreadCalls用于指示是否捕获对错误线程的调用,代码如下:
private void btnGetPage_Click(object sender, EventArgs e) { Thread th = new Thread(() => { //没有下面这一行会报线程间操作无效的异常
//设置是否捕获对错误线程的调用,调用时会访问应用程序空间的属性 Control.CheckForIllegalCrossThreadCalls = false; var req = HttpWebRequest.Create("https://www.cnblogs.com"); var resp = req.GetResponse(); Stream stream = resp.GetResponseStream(); using (StreamReader sr=new StreamReader(stream,Encoding.UTF8)) { textBox1.Text = sr.ReadToEnd(); } }); th.Start(); }
2. InvokeRequired属性
每个控件拥有InvokeRequired属性,该属性指示调用方调用控件方法时是否必须调用Invoke方法,因为调用方线程在控件线程以外。
判断InvokeRequired的值为true,在为控件调用Invoke方法,代码如下:
private void btnGetPage2_Click(object sender, EventArgs e) { var req = (HttpWebRequest)HttpWebRequest.Create("http://www.sina.com.cn"); //开始对Internet资源的异步请求 req.BeginGetResponse(AsyncCallbackImpl, req); } public void AsyncCallbackImpl(IAsyncResult ar) { //获取异步请求 WebRequest webreq = ar.AsyncState as WebRequest; var resp = webreq.EndGetResponse(ar); var stream2 = resp.GetResponseStream(); using (StreamReader sr = new StreamReader(stream2)) { var strdocument = sr.ReadToEnd(); //调用方调用控件方法时是否必须调用Invoke方法,因为调用方线程在控件线程以外 if (textBox2.InvokeRequired) { textBox2.Invoke(new Action(() => { textBox2.Text = strdocument; })); } else { textBox2.Text = strdocument; } } }
3. 扩展
控件.Invoke()中委托参数的使用示例,顺便多熟悉委托的使用。
private void btnDelegate_Click(object sender, EventArgs e) { MessageBox.Show(GetSc(GetStr)); } //01 新建一个委托 private delegate string returnStrDelegate(); //02 委托对应的方法 private string GetStr() { return "OK!"; } //03 委托作为参数调用 private string GetSc(returnStrDelegate myStrDelegate) { //调用方调用控件方法时是否必须调用Invoke方法,因为调用方线程在控件线程以外 if (this.InvokeRequired) { //调用Invoke方法 注意:返回的是object类型,需转换 return this.Invoke(myStrDelegate).ToString(); } else { return myStrDelegate(); } }