本文中使用的示例代码都是在WinForm中编写调试的,我根据是否使用await处理Task、调用异步方法/非异步方法、方法的返回值为Task/Task
public class CommonUtil
{
public static async Task AsyncGetStudentInfoHasReturn(string sname)
{
string name = $"Handle:{sname}";
var result = await Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Sub01-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("Sub01-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return new Student() { Id = "01", SName = sname, Age = 12 };
});
Console.WriteLine("Sub01-await之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
result = await Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Sub02-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("Sub02-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return new Student() { Id = "01", SName = sname, Age = 12 };
});
Console.WriteLine("Sub02-await之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return result;
}
public static async Task AsyncGetStudentInfoNoReturn(string sname)
{
string name = $"Handle:{sname}";
await Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Sub01-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("Sub01-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Sub01-await之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
await Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Sub02-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("Sub02-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Sub02-await之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
public static Task GetStudentInfoHasReturn(string sname)
{
string name = $"Handle:{sname}";
Task task = Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return new Student() { Id = "01", SName = sname, Age = 12 };
});
Console.WriteLine("Sub-TaskRun之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return task;
}
public static Task GetStudentInfoNoReturn(string sname)
{
string name = $"Handle:{sname}";
Task task = Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Sub-TaskRun之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return task;
}
}
///
/// 使用await调用返回值为Task的异步方法
///
///
///
private async void btnInvokeAsyncHasResultUseAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
var task01 = CommonUtil.AsyncGetStudentInfoHasReturn("AAA");
Thread.Sleep(2000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
await task01;//await时界面不卡顿
Console.WriteLine("【3】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Student student01 = task01.Result;//await之后获取返回值时无需再等待
Console.WriteLine("【4】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 不使用await调用返回值为Task的异步方法
///
///
///
private void btnInvokeAsyncHasResultNoAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
var task01 = CommonUtil.AsyncGetStudentInfoHasReturn("AAA");
Thread.Sleep(2000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Student student01 = task01.Result;//调用有返回值的异步方法时,省略await直接用task01.Result获取返回值时会一直等待
Console.WriteLine("【3】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 使用await调用返回值为Task的异步方法
///
///
///
private async void btnInvokeAsyncNoResultUseAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
var task01 = CommonUtil.AsyncGetStudentInfoNoReturn("AAA");
Thread.Sleep(20000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
await task01;//await时界面不卡顿,必须等CommonUtil.AsyncGetStudentInfoNoReturn("AAA")执行完最后一行代码才算await执行完毕
Console.WriteLine("【3】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 不使用await调用返回值为Task的异步方法
///
///
///
private void btnInvokeAsyncNoResultNoAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
var task01 = CommonUtil.AsyncGetStudentInfoNoReturn("AAA");//执行时界面不卡顿
Thread.Sleep(20000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 使用await调用返回值为Task的方法
///
///
///
private async void btnInvokeTaskHasResultUseAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task = CommonUtil.GetStudentInfoHasReturn("AAA");
Thread.Sleep(2000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
await task;//await时界面不卡顿
Console.WriteLine("【3】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Student student02 = task.Result;//await之后获取返回值时无需再等待
Console.WriteLine("【4】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 不使用await调用返回值为Task的方法
///
///
///
private void btnInvokeTaskHasResultNoAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task = CommonUtil.GetStudentInfoHasReturn("AAA");
Thread.Sleep(2000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Student student01 = task.Result;//通过task.Result获取返回值时界面会卡顿
Console.WriteLine("【3】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 使用await调用返回值为Task的方法
///
///
///
private async void btnInvokeTaskNoResultUseAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task = CommonUtil.GetStudentInfoNoReturn("AAA");
Thread.Sleep(2000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
await task;//await时界面不卡顿,必须等CommonUtil.GetStudentInfoNoReturn("AAA")执行完最后一行代码才算await执行完毕
Console.WriteLine("【3】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
///
/// 不使用await调用返回值为Task的方法
///
///
///
private void btnInvokeTaskNoResultNoAwait_Click(object sender, EventArgs e)
{
Console.WriteLine("【1】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
var task01 = CommonUtil.GetStudentInfoNoReturn("AAA");//执行时界面不卡顿
Thread.Sleep(2000);
Console.WriteLine("【2】Main【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
1.1、async方法中可以调用有返回值的async方法、没返回值的async方法、有返回值的非async方法、没返回值的非async方法
1.2、非async方法中可以调用没返回值的async方法、有返回值的非async方法、没返回值的非async方法
1.3、非async方法中不能调用有返回值的async方法,因为有返回值的async方法必须使用await获取返回值,而非async方法中不能使用await
2.1、async方法有返回值时必须使用await让主线程等待任务执行完毕并获取返回值
2.2、async方法没返回值时可以使用await让主线程等待任务执行完毕,也可以不使用await在主线程空闲时再等待任务执行完毕
2.3、主线程什么时候是空闲呢?
3.1、使用await获取async方法、非async方法的返回值时界面不卡顿
3.2、使用task.Result获取非async方法的返回值时界面会卡顿
3.3、使用task.Result无法获取async方法的返回值,必须使用await获取async方法的返回值