C# Task(任務調度)


一個Task表示一個異步操作,Task的創建和執行都是獨立的,因此可以對關聯操作的執行擁有完全的控制權。

一:Task的優勢
1: Task支持線程的取消、完成、失敗通知等交互性操作
2: Task支持線程執行的先后次序

 

Task t = new Task(() =>
{
    
});
t.ContinueWith((task) =>
{
    
});
t.Start();

  

二:Task的完成狀態
任務Task有這樣一些屬性,讓我們查詢任務完成時的狀態:
1: IsCanceled,因為被取消而完成
2: IsCompleted,成功完成
3: IsFaulted,因為發生異常而完成

CancellationTokenSource cts = new CancellationTokenSource();
Task<int> t = new Task<int>(() => Add(cts.Token), cts.Token);
t.Start();
t.ContinueWith(TaskEnded);
//等待按下任意一個鍵取消任務
Console.ReadKey();
cts.Cancel();

  

任務Task創建方式

方式一、new Task 無返回值

Task task = new Task(() =>{});
task.Start();

  

new Task 有返回值的方式,Task 與 ContinueWith

//先執行Task
Task<int> task = new Task<int>(() => { 
    return 0; 
});
//其次執行ContinueWith
task.ContinueWith(t =>
{
    int result = t.Result;
});
task.Start();

   

方式二、使用 TaskMethod 無返回值

Task task = new Task(() => TaskMethod("Task 2"));
task.Start();

    

方式三、Task.Run

Task task = Task.Run(() => TaskMethod("Task 3"));

    

方式四、直接異步的方法

Task.Factory.StartNew(() => TaskMethod("Task 3"));

方式五、異步

Task.Run(async () =>
{
    await Task.Factory.StartNew(() =>
    {
                        
    });
});

  

Task任務並行

List<Task> taskList = new List<Task>();
taskList.Add(Task.Run(() =>
{

}));
taskList.Add(Task.Run(() =>
{

}));
taskList.Add(Task.Run(() =>
{

}));

    

//主線程阻塞,等待結束
Task.WaitAll(taskList.ToArray());
主線程 Code ....執行

方式三、異步非阻塞

Task[] tlist = new Task[] { 
    Task.Factory.StartNew(() => { 
        Thread.Sleep(3000); 
    }), 
    Task.Factory.StartNew(() => {
        Thread.Sleep(90000);
    }) 
};
Task.WhenAny(tlist).ContinueWith((s) => {
    return s;
});

    

使用IProgress實現異步編程的進程通知

private void btnSub_Click(object sender, RoutedEventArgs e)
{
    Task task = Display();
}
void DoProcessing(IProgress<int> progress)
{
    if (progress != null)
    {
        progress.Report(1);
    }
}

async Task Display()
{
    //當前線程
    var progress = new Progress<int>(percent =>
    {
        this.Title = percent.ToString();
    });
    //線程池線程
    await Task.Run(() => DoProcessing(progress));
}

  

本文來源參考:https://www.cnblogs.com/zhaoshujie/p/11082753.html 

什么是並行
並行是指兩個或者多個事件在同一時刻發生
在程序運行中,並行指多個CPU核心同時執行不同的任務;對於單核心CPU,嚴格來說是沒有程序並行的。並行是為了提高任務執行效率,更快的獲取結果。

與並發的區別
並發是指兩個或者多個事件在同一時段發生。
相對於並行,並發強調的是同一時段,是宏觀上的同時發生。實際上,同一時刻只有一個任務在被執行,多個任務是分時地交替執行的。並發是為了更合理地分配資源。

實現並行,我們要借助進程和線程。
進程是正在運行的程序的實例。
線程被包含在進程之中,是進程中的實際運作單位。

前台線程和后台線程
.NET把線程分為前台線程和后台線程,兩者幾乎相同,唯一的區別是,前台線程會阻止進程的正常退出,后台線程則不會。

線程池 ThreadPool
線程的創建和銷毀要耗費很多時間,而且過多的線程不僅會浪費內存空間,還會導致線程上下文切換頻繁,影響程序性能。為改善這些問題,.NET運行時(CLR)會為每個進程開辟一個全局唯一的線程池來管理其線程。

多線程
1、在執行一個較長時間的任務時,不能阻塞UI界面響應,必須通過后台線程處理;
2、在執行批量計算密集型任務時,采用多線程技術可以提高運行效率;

傳統使用的多線程技術有:
Thread & ThreadPool
Timer
BackgroundWorker

Task內部也是對ThreadPool的封裝

采用並行編程方法:
Parallel.For(1, 10000, x=>
{
bool b = IsPrimeNumber(x);
Console.WriteLine($"{i}:{b}");
});
//使用並行循環處理數據更新
List<string> lists = new List<string>();
System.Threading.Tasks.Parallel.For(0, lists.Count, (int i) =>
{
string sql = string.Format("update table1 set IsExit =1 where Id='{0}'", lists[i]);
Execute(sql);
});

和Task類似,Parallel類仍然是對ThreadPool的封裝。

需要通知一個任務結束,或一個任務等待某個條件進入下一個狀態,這就需要用到任務同步的技術。
采用WaitOne來等待

異步編程模型(await、async)

非UI線程不能訪問UI控件,可以使用Invoke

多線程環境下的數據安全
private static ConcurrentDictionary<int, string> Dic = new ConcurrentDictionary<int, string>();
//添加操作
Dic.TryAdd(i, i.ToString());

多線程的異常處理
基本原則:不要輕易捕獲根異常;
多線程的內部異常不會傳播到主線程,應該在內部進行處理,可以通過事件推到主線程來;
應用程序層面可以捕獲根異常,做一些記錄工作,切不可隱匿異常。
將異常包裝成事件推送到主線程,交給主線程處理。
參考:https://www.cnblogs.com/seabluescn/p/12973936.html

異步編程中,線程之間只要互不影響,考慮同步問題即可。而在並行編程中,則要求多個線程在同一時刻同時運行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM