之前使用Thread和Task启动多线程时都会遇到一个麻烦,就是如何反馈结果。在代码里就是如何设计回调函数。如果带界面还得考虑UI线程的问题。
而使用async,await可以达到两个效果。
1 不用设计回调函数,直接按单线程的格式写。
2 不用考虑UI线程问题。
下面用两个例子来说明:
示例1 纯后端代码
使用的示例如下:
internal class asyncTest{// 方法1 使用async, await关键字public async Task<int> Test1(){await Task.Delay(1000); // 模拟耗时操作return 1;}// 方法2 使用 task启动线程public delegate void LogUpdateHandler(string message);public event LogUpdateHandler? LogUpdateEvent;public void Test2(){Task.Run(() =>{Thread.Sleep(1000);LogUpdateEvent?.Invoke("Task: result=2");});}}
调用代码如下:
void Main()
{Console.WriteLine("Hello, World!");asyncTest test = new asyncTest();int result1 = await test.Test1();Console.WriteLine("async 、await: result=" + result1.ToString());test.LogUpdateEvent += fun;test.Test2();Console.ReadLine();
}void fun(string meg) {Console.WriteLine(meg);
}
执行结果:
可以看到,效果两种方法是一样的。但是async,await方法要简洁很多,也不用写回调函数。
示例2 带有UI界面:
一样的两个示例方法:
internal class asyncTest
{public async Task<int> Test1(){await Task.Delay(1000); // 模拟耗时操作return 1;}public delegate void LogUpdateHandler(string message);public event LogUpdateHandler? LogUpdateEvent;public void Test2(){Task.Run(() =>{Thread.Sleep(1000);LogUpdateEvent?.Invoke("Task: result=2");});}
}
页面调用示例:
private async void Button_Click(object sender, RoutedEventArgs e){asyncTest test = new asyncTest();int result1 = await test.Test1();this.listbox01.Items.Add("async 、await: result=" + result1.ToString());test.LogUpdateEvent += AsyncTest_LogUpdateEvent;test.Test2();}private void AsyncTest_LogUpdateEvent(string message)
{// 使用 Dispatcher.Invoke 在 UI 线程上更新页面控件Dispatcher.Invoke(() =>{this.listbox01.Items.Add(message);});
}
结果:
同样,async,await方法要简洁很多,并且直接调用UI控件。
而task方法,还得通过 Dispatcher.Invoke 来调用UI控件。