之前使用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控件。