您好,登錄后才能下訂單哦!
本篇內容介紹了“C#怎么Task執行任務”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
代碼:
//任務 Func<int> Funcs = () => { Console.WriteLine("任務開始"); return 1 + 1; }; //執行任務 Task<int> printRes = Task.Run(Funcs); //等待任務完成 printRes.GetAwaiter().OnCompleted(() => { Console.WriteLine("異步執行結果:" + printRes.Result); });
運行:
任務開始
異步執行結果:2
眾所周知,方法體內代碼是從上往下執行的,在我們工作中經常會遇到一些需要延時執行,但又必須按順序來執行的需求。這要怎么解決呢。微軟官方提供的Task API就是專門來解決這個問題的。那么下面就開始吧。
新建一個Winfrom項目
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace 線程2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Task task1 = new Task(() => { Thread.Sleep(400); Console.WriteLine("task1"); }); Task task2 = new Task(() => { Thread.Sleep(300); Console.WriteLine("task2"); }); Task task3 = new Task(() => { Thread.Sleep(200); Console.WriteLine("task3"); }); Task task4 = new Task(() => { Thread.Sleep(100); Console.WriteLine("task4"); }); task1.Start(); task2.Start(); task3.Start(); task4.Start(); } } }
運行:
由于各個任務內部延時不同,最先執行的Task1,反而最后一個執行完,如果既要做延時操作,又要求從任務按順序執行,要怎么解決呢?
修改代碼:
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace 線程2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private List<Task> TaskList = new List<Task>(); private void Form1_Load(object sender, EventArgs e) { Task task1 = new Task(() => { Thread.Sleep(400); Console.WriteLine("task1"); }); Task task2 = new Task(() => { Thread.Sleep(300); Console.WriteLine("task2"); }); Task task3 = new Task(() => { Thread.Sleep(200); Console.WriteLine("task3"); }); Task task4 = new Task(() => { Thread.Sleep(100); Console.WriteLine("task4"); }); TaskList.Add(task1); TaskList.Add(task2); TaskList.Add(task3); TaskList.Add(task4); foreach (Task task in TaskList) { task.Start(); task.Wait(); } } } }
運行:
用上面的方法雖然有效,你可以看看,點擊界面的時候,界面處鼠標指針會一直轉圈,導致winfrom界面卡住,無法操作,這是因為使用Thread.Sleep 導致主線程阻塞,下面就來解決UI界面卡死的問題。
代碼:
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace 線程2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private List<Task> TaskList = new List<Task>(); private void Button_Calculate_Click(object sender, EventArgs e) { Task task1 = new Task(async () => { await Task.Delay(TimeSpan.FromSeconds(4)); Console.WriteLine("task1"); }); Task task2 = new Task(async () => { await Task.Delay(TimeSpan.FromSeconds(3)); Console.WriteLine("task2"); }); Task task3 = new Task(async () => { await Task.Delay(TimeSpan.FromSeconds(2)); Console.WriteLine("task3"); }); Task task4 = new Task(async () => { await Task.Delay(TimeSpan.FromSeconds(1)); Console.WriteLine("task4"); }); TaskList.Add(task1); TaskList.Add(task2); TaskList.Add(task3); TaskList.Add(task4); foreach (Task task in TaskList) { task.Start(); task.Wait(); } } } }
運行:
用異步方式雖然界面不會卡住,但另一個問題來了,task.wait()方法似乎沒有效果。里面的任務隊列依然沒有按順序來執行。那么如何即使用異步執行,也不阻塞主線程,而且要任務按順序來執行呢?
代碼:
private void Test() { Task.Run(() => { Task t1 = new Task(() => { Thread.Sleep(2000); Console.WriteLine("t1"); num = 1; }); t1.Start(); t1.Wait(); Task t2 = new Task(() => { Thread.Sleep(1000); Console.WriteLine("t2"); num = 3; }); t2.Start(); t2.Wait(); Console.WriteLine("線程執行完畢"); }); }
運行:
效果是實現了,代碼看起來好搓啊,強迫癥都犯了,沒關系,可以使用更優雅的寫法:
private async void Test() { await Task.Run(async () => { await Task.Delay(4000); Trace.WriteLine("第1個線程執行"); }); await Task.Run(async () => { await Task.Delay(3000); Trace.WriteLine("第2個線程執行"); }); await Task.Run(async () => { await Task.Delay(2000); Trace.WriteLine("第3個線程執行"); }); }
運行:
到此為止,功能就實現了,這個需求在Unity3d中使用協程很簡單的幾句就可以搞定,但在Winfrom等項目的開發中,確實有點繁瑣。
下面的代碼我不認為是一個很好的寫法,需要添加任務后,還得手動去調用,如果能添加到任務隊列就不管了,讓其自己自動按順序來執行任務,豈不是更好,讀者如果有興趣自己去完善這個猜想。另外,在游戲開發中,比如RGP項目中,有專門的任務系統,它和我這個帖子的概念不能混為一談,RPG任務系統更多的偏向數據的存取,來獲取任務的完成狀態。
using System; using System.Collections.Generic; using System.Threading.Tasks; namespace Utils { public class TaskQueue { /// <summary> /// 任務列表 /// </summary> private List<Task> TaskList = null; /// <summary> /// 是否在執行任務中 /// </summary> private bool isPerformTask = false; /// <summary> /// 執行完任務的回調 /// </summary> public Action CallBack = null; private static TaskQueue _instance = null; public static TaskQueue Instance { get { if (_instance == null) _instance = new TaskQueue(); return _instance; } } /// <summary> /// 添加任務 /// </summary> /// <param name="task"></param> public void AddTask(Task task) { if (isPerformTask) { Console.WriteLine("[TaskQueue]任務正在執行中,此時不能做賦值操作"); return; } if (task != null) { TaskList.Add(task); } } /// <summary> /// 執行任務 /// </summary> public void PerformTask() { if (isPerformTask) { Console.WriteLine("[TaskQueue]任務正在執行中,不可重復調用"); return; } if (TaskList == null || TaskList.Count == 0) { Console.WriteLine("[TaskQueue]任務列表為空"); return; } Task.Run(() => { isPerformTask = true; foreach (Task item in TaskList) { item.Start(); item.Wait(); } TaskList.Clear(); isPerformTask = false; if (CallBack != null) CallBack(); }); } private TaskQueue() { TaskList = new List<Task>(); } } }
調用:
Task task1 = new Task(() => { Thread.Sleep(1000); Console.WriteLine("t1"); }); Task task2 = new Task(() => { Thread.Sleep(2000); Console.WriteLine("t2"); }); Task task3 = new Task(() => { Console.WriteLine("t3"); }); Action callback = () => { Console.WriteLine("所有任務執行完成"); }; TaskQueue.Instance.AddTask(task1); TaskQueue.Instance.AddTask(task2); TaskQueue.Instance.AddTask(task3); TaskQueue.Instance.CallBack = callback; TaskQueue.Instance.PerformTask();
運行:
“C#怎么Task執行任務”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。