C# async await 学习笔记2
C# async await 学习笔记1(http://www.cnblogs.com/siso/p/3691059.html)
提到了ThreadId是一样的,突然想到在WinForm中,非UI线程是无法直接更新UI线程上的控件的问题。
于是做了如下测试:
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.Tasks; using System.Threading; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Task<string> LongTimeTask() { tbResult.Text += "LongTimeTask开始:" + DateTime.Now.ToString() + "\r\n"; Task<string> task = new Task<string>(() => { Thread.Sleep(5000); return "这是任务返回值"; }); task.Start(); tbResult.Text += "LongTimeTask结束:" + DateTime.Now.ToString() + "\r\n"; return task; } async void AsyncCall() { tbResult.Text += "AsyncCall开始:" + DateTime.Now.ToString() + "\r\n"; string result = await LongTimeTask(); //await调用的方法需要返回Task或Task<T>,且调用await所在的方法要有async关键字 tbResult.Text += "AsyncCall:" + result + "\r\n"; tbResult.Text += "AsyncCall结束:" + DateTime.Now.ToString() + "\r\n"; } private void button1_Click(object sender, EventArgs e) { tbResult.Text += "Main开始:" + DateTime.Now.ToString() + "\r\n"; AsyncCall(); tbResult.Text += "Main结束:" + DateTime.Now.ToString() + "\r\n"; } } }
发现,在AsyncCall中,可以直接访问TextBox(tbResult),如果对上面的测试觉得没什么奇怪,大家可以先看下面的代码。
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 Form2 : Form { public Form2() { InitializeComponent(); } void LongTimeTask() { Thread.Sleep(5000); tbResult.Text += "AsyncCall结束:" + DateTime.Now.ToString() + "\r\n"; } private void button1_Click(object sender, EventArgs e) { tbResult.Text += "Main开始:" + DateTime.Now.ToString() + "\r\n"; Thread t = new Thread(LongTimeTask); t.Start(); tbResult.Text += "Main结束:" + DateTime.Now.ToString() + "\r\n"; } } }
运行到 LongTimeTask的tbResult.Text时,提示:线程间操作无效: 从不是创建控件“tbResult”的线程访问它。
为了能在非UI线程中访问到UI线程中的控件,于是需作如下修改:
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 Form2 : Form { delegate void UpdateUIDelegate(); UpdateUIDelegate updateUIDelegate; public Form2() { InitializeComponent(); updateUIDelegate = new UpdateUIDelegate(UpdateUI); } void UpdateUI() { if (tbResult.InvokeRequired) { tbResult.Invoke(updateUIDelegate); } else { tbResult.Text += "AsyncCall结束:" + DateTime.Now.ToString() + "\r\n"; } } void LongTimeTask() { Thread.Sleep(5000); UpdateUI(); } private void button1_Click(object sender, EventArgs e) { tbResult.Text += "Main开始:" + DateTime.Now.ToString() + "\r\n"; Thread t = new Thread(LongTimeTask); t.Start(); tbResult.Text += "Main结束:" + DateTime.Now.ToString() + "\r\n"; } } }