Task
任务,背后的实现也是使用了线程池线程,但它的性能优于ThreadPoll,因为它使用的不是线程池的全局队列,而是使用的本地队列,使线程之间的资源竞争减少。同时Task提供了丰富的API来管理线程、控制。但是相对前面的两种耗内存,Task依赖于CPU对于多核的CPU性能远超前两者,单核的CPU三者(thread、threadpool、Task)的性能没什么差别
class Program
{
/// <summary>
/// 启动方式
/// </summary>
public static void StartWay()
{
var task1 = new Task(() =>
{
Console.WriteLine("Hello,task");
});
task1.Start();
var task2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Hello,task started by task factory");
});
}
/// <summary>
/// 生命周期测试
/// </summary>
public static void LifeCircle()
{
var task1 = new Task(() =>
{
Console.WriteLine("Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Finish");
});
Console.WriteLine("Before start:" + task1.Status);
task1.Start();
Console.WriteLine("After start:" + task1.Status);
task1.Wait();
Console.WriteLine("After Finish:" + task1.Status);
}
/// <summary>
/// 等待所有任务完成
/// </summary>
public static void WaitAll()
{
string zhe = "";
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 1 Finish");
zhe = "fswet";
});
var task2 = new Task(() =>
{
Console.WriteLine("Task 2 Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 2 Finish");
});
task1.Start();
task2.Start();
Task.WaitAll(task1, task2);
Console.WriteLine("WaitAll task finished!"+ zhe);
}
/// <summary>
/// 等待任意一个执行任务完成
/// </summary>
public static void WaitAny()
{
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 1 Finish");
});
var task2 = new Task(() =>
{
Console.WriteLine("Task 2 Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 2 Finish");
});
task1.Start();
task2.Start();
Task.WaitAny(task1, task2);
Console.WriteLine("WaitAny task finished!");
}
/// <summary>
/// 任务回调方法
/// </summary>
public static void ContinueWith()
{
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 1 Finish");
});
var task2 = new Task(() =>
{
Console.WriteLine("Task 2 Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 2 Finish");
});
task1.Start();
task2.Start();
var result = task1.ContinueWith<string>(task =>
{
Console.WriteLine("task1 finished!");
return "This is task1 result!";
});
Console.WriteLine(result.Result.ToString());
var result2 = task2.ContinueWith<string>(task =>
{
Console.WriteLine("task2 finished!");
return "This is task2 result!";
});
Console.WriteLine(result2.Result.ToString());
}
/// <summary>
/// 取消任务
/// </summary>
public static void Cancel()
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
for (var i = 0; i < 1000; i++)
{
System.Threading.Thread.Sleep(1000);
if (token.IsCancellationRequested)
{
Console.WriteLine("Abort mission success!");
return;
}
}
}, token);
token.Register(() =>
{
Console.WriteLine("Canceled");
});
Console.WriteLine("Press enter to cancel task...");
Console.ReadKey();
tokenSource.Cancel();
Console.ReadKey();//这句忘了加,程序退出了,看不到“Abort mission success!“这个提示
}
static void Main(string[] args)
{
//Console.WriteLine("StartWay is runing");
//StartWay();
//Console.WriteLine("LifeCircle is runing");
//LifeCircle();
//Console.WriteLine("WaitAll is runing");
WaitAll();
//Console.WriteLine("WaitAny is runing");
//WaitAny();
//Console.WriteLine("ContinueWith is runing");
//ContinueWith();
//Console.WriteLine("Cancel is runing");
//Cancel();
Console.Read();
}
}
.Net 提供了3中异步编程模型
- TAP(基于任务的异步模式):使用单一方法表示异步操作的开始和结束,是.Net中进行异步编程的推荐方法。(.Net Framework 4中引入的)
- EAP(基于事件的异步模式):提供异步行为的基于事件的旧模型。 这种模式需要后缀为 Async 的方法,以及一个或多个事件、事件处理程序委托类型和 EventArg 派生类型。 EAP 是在 .NET Framework 2.0 中引入的。 不建议新的开发使用此模式。
- APM(异步编程模型):(也称为 IAsyncResult 模式),这是使用 IAsyncResult 接口提供异步行为的旧模型。 在这种模式下,同步操作需要 Begin 和 End 方法(例如,BeginWrite 和 EndWrite以实现异步写入操作)。 不建议新的开发使用此模式。
TAP(基于任务的异步模式)
C# 异步编程的核心是 Task 和 Task 对象(深入了解Task和Task),这两个对象对异步操作建模。它们受关键字 async 和 await 的支持(二者是异步编程的核心关键字)。通过这两个关键字,可以使用 .NET Framework、.NET Core 或 Windows 运行时中的资源,轻松创建异步方法(几乎与创建同步方法一样轻松)。 使用 async 关键字定义的异步方法简称为“异步方法”。await 关键字控制执行 await 的方法的调用方,且它最终允许 UI 具有响应性或服务具有灵活性。
async是用来修饰方法,表示此方法可以是异步方法,如果方法里不包含await,则此方法相当于普通的同步方法。
await是使用在被async修饰的方法里。
await 后面跟上一个异步操作Task,当程序执行到此行代码时,由于有await的修饰,会等待异步操作Task执行,Task执行完成后才会执行此方法里await这一行后面的代码,
但是外部调用async方法的地方,不会等待Task完成,就执行后面的代码。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main function begin...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
Test();
Console.WriteLine("Main function end");
Console.ReadLine();
}
public static async void Test()
{
Console.WriteLine("test begin...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
await Task.Run(()=>{ Work1(); });
await Task.Run(() => { Work2(); });
await Task.Run(() => { Work3(); });
Console.WriteLine("test end---");
}
public static void Work1()
{
Console.WriteLine("Work1 start...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(6000);
Console.WriteLine("Work1 end---");
}
public static void Work2()
{
Console.WriteLine("Work2 start...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(6000);
Console.WriteLine("Work2 end---");
}
public static void Work3()
{
Console.WriteLine("Work3 start...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(6000);
Console.WriteLine("Work3 end---");
}
}
从测试结果,可以看出,Test方法还没有执行结束,Main方法里调用Test方法这一行后面的代码,已经执行,无需等待Test方法。
Test方法由于被async修饰,表明这个可以是异步方法,方法内部await修饰的Task,执行到这一行代码时,会等待Task执行完成后,才会执行Test方法里下一行的代码。