关于async与await的一点测试
Winform
private async Task DoAsync() { Console.WriteLine("DoAsync_Befor:" + Thread.CurrentThread.ManagedThreadId); for (int i = 0; i < 10; i++) { await Task.Run(() => { //Thread.Sleep(100); Console.WriteLine("in:" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("DoAsync_After:" + Thread.CurrentThread.ManagedThreadId); } } private void button2_Click(object sender, EventArgs e) { Console.WriteLine("button2_Click_befor:" + Thread.CurrentThread.ManagedThreadId); DoAsync(); Console.WriteLine("button2_Click_after:" + Thread.CurrentThread.ManagedThreadId); //Console.Read(); }
Console
static void Main(string[] args) { Console.WriteLine("Main_befor:" + Thread.CurrentThread.ManagedThreadId); DoAsync(); Console.WriteLine("Main_after:" + Thread.CurrentThread.ManagedThreadId); Console.Read(); } private static async Task DoAsync() { Console.WriteLine("DoAsync_Befor:" + Thread.CurrentThread.ManagedThreadId); for (int i = 0; i < 10; i++) { await Task.Run(() => { Thread.Sleep(100); Console.WriteLine("in:" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("DoAsync_After:" + Thread.CurrentThread.ManagedThreadId); } }
Winform 的DoAsync_After 始终是1,即 UI线程
而Console输出有多个情况,即Task.Run(...)中使用的线程,
所以在Winform中async与await是做特定处理的
//=========================测试代码2==========================
private async void Form1_Load(object sender, EventArgs e) { try { Console.WriteLine($"Load Begin {Thread.CurrentThread.ManagedThreadId}"); var r= AddAsync(4, 5); // var r = await AddAsync(4, 5); Console.WriteLine(r); Console.WriteLine("Load Complated"); } catch (Exception ex) { Console.WriteLine(ex.Message + Thread.CurrentThread.ManagedThreadId); } } private async Task<int> AddAsync(int a,int b) { //Thread.Sleep(1000); Console.WriteLine($"Call AddAsync Begin {Thread.CurrentThread.ManagedThreadId}"); Func<int> fac = () => { Thread.Sleep(1000); Console.WriteLine($"In Call AddAsync {Thread.CurrentThread.ManagedThreadId}"); return a + b; }; Console.WriteLine($"Call AddAsync End {Thread.CurrentThread.ManagedThreadId}"); return await Task.Run<int>(fac); }
调整为
// var r= AddAsync(4, 5);
var r = await AddAsync(4, 5);
后的输出是
官方Demo
public partial class MainWindow : Window { // Mark the event handler with async so you can use await in it. private async void StartButton_Click(object sender, RoutedEventArgs e) { // Call and await separately. //Task<int> getLengthTask = AccessTheWebAsync(); //// You can do independent work here. //int contentLength = await getLengthTask; int contentLength = await AccessTheWebAsync(); resultsTextBox.Text += String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); } // Three things to note in the signature: // - The method has an async modifier. // - The return type is Task or Task<T>. (See "Return Types" section.) // Here, it is Task<int> because the return statement returns an integer. // - The method name ends in "Async." async Task<int> AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task<string>. That means that when you await the // task you'll get a string (urlContents). Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); // You can do work here that doesn't rely on the string from GetStringAsync. DoIndependentWork(); // The await operator suspends AccessTheWebAsync. // - AccessTheWebAsync can't continue until getStringTask is complete. // - Meanwhile, control returns to the caller of AccessTheWebAsync. // - Control resumes here when getStringTask is complete. // - The await operator then retrieves the string result from getStringTask. string urlContents = await getStringTask; // The return statement specifies an integer result. // Any methods that are awaiting AccessTheWebAsync retrieve the length value. return urlContents.Length; } void DoIndependentWork() { resultsTextBox.Text += "Working . . . . . . .\r\n"; } }
注意Demo中可以用2种方式调用AccessTheWebAsync,即同步调用(带await)与 异步调用
--------------------------------以下写法会导致UI卡死 ------------------------------
private async void Form1_Load(object sender, EventArgs e) { try { Console.WriteLine($"Load Begin {Thread.CurrentThread.ManagedThreadId}"); var r= AddAsync(4, 5); //var r = await AddAsync(4, 5); //Console.WriteLine(r); Console.WriteLine(r.Result); Console.WriteLine("Load Complated"); } catch (Exception ex) { Console.WriteLine(ex.Message + Thread.CurrentThread.ManagedThreadId); } } private async Task<int> AddAsync(int a,int b) { //Thread.Sleep(1000); Console.WriteLine($"Call AddAsync Begin {Thread.CurrentThread.ManagedThreadId}"); Func<int> fac = () => { Thread.Sleep(1000); Console.WriteLine($"In Call AddAsync {Thread.CurrentThread.ManagedThreadId}"); return a + b; }; Console.WriteLine($"Call AddAsync End {Thread.CurrentThread.ManagedThreadId}"); //var t= Task.Run<int>(fac); //return t.Result; return await Task.Run<int>(fac); }
需要改成这样
while (!r.IsCompleted) { Application.DoEvents(); Thread.Sleep(100); } Console.WriteLine(r.Result);