01.異步任務
class Program
{
static void Main(string[] args)
{
Simple simple=new Simple();
simple.DoRun();
Console.WriteLine("main");
Console.ReadKey();
}
class Simple
{
Stopwatch sw=new Stopwatch();
public void DoRun()
{
Console.WriteLine("Caller: Before call");
ShowDealyAsync();
Console.WriteLine("Caller: After call");
}
private async void ShowDealyAsync()
{
sw.Start();
Console.WriteLine(" Before Delay: {0}", sw.ElapsedMilliseconds);
await Task.Delay(3000); //異步延時
Console.WriteLine("延時觸發");
Console.WriteLine(" After Delay : {0}", sw.ElapsedMilliseconds);//後續部分
}
}
}
class Program
{
static void Main(string[] args)
{
AsyncTaskOne();
for (int i = 0; i < 10; i++)
{
// Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString()); //目前線程的ID
Thread.Sleep(500);
Console.WriteLine($"main:+{i}");
}
Console.ReadKey();
}
private async static void AsyncTaskOne()
{
await Task.Run(() =>
{
// Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
Console.WriteLine($"{Thread.CurrentThread.Name}:+{i}");
Console.WriteLine();
}
});
}
}
03.開啟一個任務的三種方式
static void Main(string[] args)
{
AsyncTask();
Console.ReadKey();
}
/// <summary>
/// 開啟一個任務的三種方式
/// </summary>
private static void AsyncTask()
{
//1.new方式執行個體化一個Task,需要通過Start方法啟動
Task task1=new Task(() =>
{
Thread.Sleep(500);
Console.WriteLine($"task1的線程ID為{Thread.CurrentThread.ManagedThreadId}");
});
task1.Start();
//2.Task.Factory.StartNew(Action action)建立和啟動一個Task
Task task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(800);
Console.WriteLine($"task2的線程ID為{Thread.CurrentThread.ManagedThreadId}");
});
//3.Task.Run(Action action)将任務放線上程池隊列,傳回并啟動一個Task
Task task3=Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine($"task3的線程ID為{Thread.CurrentThread.ManagedThreadId}");
});
Console.WriteLine("Main");
}
04.建立有傳回值的Task
task.Resut擷取結果時會阻塞線程,即如果task沒有執行完成,會等待task執行完成擷取到Result,然後再執行後邊的代碼,
/// <summary>
/// 帶有傳回值
/// </summary>
private static void AsyncTaskTwo()
{
Task<string> task1 = new Task<string>(() => $"task1的線程ID是{Thread.CurrentThread.ManagedThreadId}");
task1.Start();
Task<string> task2=Task.Factory.StartNew(() => { return $"task2的線程ID是{Thread.CurrentThread.ManagedThreadId}"; },TaskCreationOptions.LongRunning);
Task<string> task3 = Task<string>.Run(() =>
{
return $"task1的線程ID是{Thread.CurrentThread.ManagedThreadId}";
});
Console.WriteLine("主線程");
Console.WriteLine("task1結果:" + task1.Result);
Console.WriteLine("task2結果:" + task2.Result);
Console.WriteLine("task3結果:" + task3.Result);
}
05。同步執行
static void Main(string[] args)
{
AsyncTaskThree();
Console.WriteLine("主線程ID:"+ Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}
//task.RunSynchronously() 用于同步執行Task任務
private static void AsyncTaskThree()
{
Task task=new Task(() =>
{
Thread.Sleep(500);
Console.WriteLine("執行Task結束!");
});
//同步執行,task會阻塞主線程
task.RunSynchronously();
}
06.
Task的Wait/WaitAny/WaitAll
task.Wait() 表示等待task執行完畢,功能類似于thead.Join(); Task.WaitAll(Task[] tasks) 表示隻有所有的task都執行完成了再解除阻塞; Task.WaitAny(Task[] tasks) 表示隻要有一個task執行完畢就解除阻塞
static void Main(string[] args)
{
ThreadblockTwo();
Console.WriteLine("主線程執行完畢!");
Console.WriteLine("主線程ID:"+ Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}
private static void ThreadblockTwo()
{
Task task1=new Task(() =>
{
Thread.Sleep(2000);
Console.WriteLine("線程1執行完畢!");
});
task1.Start();
Task task2 = new Task(() =>
{
Thread.Sleep(3000);
Console.WriteLine("線程2執行完畢!");
});
task2.Start();
//阻塞主線程。task1,task2都執行完畢再執行主線程
//task1.Wait(); task2.Wait(); //可以實作相同的功能
Task.WaitAll(new Task[]{task1,task2});
//Task.WaitAny(); //task 執行完畢就會解除線程阻塞
}
07.
所有task執行完畢(或者任一task執行完畢)後,開始執行後續操作
task.WhenAll(Task[] tasks) 表示所有的task都執行完畢後再去執行後續的操作, task.WhenAny(Task[] tasks) 表示任一task執行完畢後就開始執行後續操作
static void Main(string[] args)
{
ThreadblockThree();
Console.WriteLine("主線程執行完畢!");
Console.WriteLine("主線程ID:"+ Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}
private static void ThreadblockThree()
{
Task task1 = new Task(() =>
{
Thread.Sleep(500);
Console.WriteLine("線程1執行完畢!");
});
task1.Start();
Task task2 = new Task(() =>
{
Thread.Sleep(1000);
Console.WriteLine("線程2執行完畢!");
});
task2.Start();
//task1,task2執行完了後執行後續操作
Task.WhenAll(task1, task2).ContinueWith((Task t) =>
{
Thread.Sleep(100);
Console.WriteLine("執行後續操作完畢!");
});
//等同于
//Task.Factory.ContinueWhenAll(new Task[] { task1, task2 }, (Task[] t) =>
// {
// Thread.Sleep(100);
// Console.WriteLine("執行後續操作");
//});
}
08.
Task的任務取消(CancellationTokenSource)
private static void CancelTask()
{
CancellationTokenSource source=new CancellationTokenSource();
int index = 0;
Thread thread1=new Thread(() =>
{
while (source.IsCancellationRequested==false )
{
Thread.Sleep(500);
Console.WriteLine($"第{++index}次執行");
}
});
thread1.Start();
//source.CancelAfter(5000) 實作5秒後自動取消任務
//source.CancelAfter(3000);
Thread.Sleep(3000);
// source.Cancel()方法請求取消任務,IsCancellationRequested會變成true
//設定一個狀态,設定該對象一個熟悉為true而已,也就是設定cts.IsCancellationRequested為ture。
//是以他根本沒有真正的去取消線程的執行,隻是設定一個狀态而已。
source.Cancel();
Console.WriteLine(source.IsCancellationRequested);
}
09.source.Token.Register(Action action) 注冊取消任務觸發的回調函數,即任務被取消時注冊的action會被執行
// source.Token.Register(Action action) 注冊取消任務觸發的回調函數
// 即任務被取消時注冊的action會被執行
private static void CancelTaskTwo()
{
CancellationTokenSource source=new CancellationTokenSource();
//注冊任務取消的事件
source.Token.Register(() =>
{
//第5次執行在取消回調後列印,這是因為
//執行取消的時候第5次任務已經通過了while()判斷,任務已經執行中了
Console.WriteLine("任務取消後的回調!");
});
int index = 0;
Task task=new Task(() =>
{
while (!source.IsCancellationRequested)
{
Thread.Sleep(1000);
Console.WriteLine($"第{++index}次執行,線程運作中...");
}
});
task.Start();
source.CancelAfter(5000);//延時取消
}