文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C#怎么Task执行任务

2023-07-02 08:33

关注

本篇内容介绍了“C#怎么Task执行任务”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Task执行任务,等待任务完成

代码:

//任务Func<int> Funcs = () =>{    Console.WriteLine("任务开始");    return 1 + 1;}; //执行任务Task<int> printRes = Task.Run(Funcs); //等待任务完成printRes.GetAwaiter().OnCompleted(() =>{    Console.WriteLine("异步执行结果:" + printRes.Result);        });

运行:

任务开始
异步执行结果:2

C# Task任务队列

需求

众所周知,方法体内代码是从上往下执行的,在我们工作中经常会遇到一些需要延时执行,但又必须按顺序来执行的需求。这要怎么解决呢。微软官方提供的Task API就是专门来解决这个问题的。那么下面就开始吧。

基本的Task用法

新建一个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();        }    }}

运行:

C#怎么Task执行任务

由于各个任务内部延时不同,最先执行的Task1,反而最后一个执行完,如果既要做延时操作,又要求从任务按顺序执行,要怎么解决呢?

让Task任务按顺序执行

修改代码:

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();            }        }    }}

运行:

C#怎么Task执行任务

用上面的方法虽然有效,你可以看看,点击界面的时候,界面处鼠标指针会一直转圈,导致winfrom界面卡住,无法操作,这是因为使用Thread.Sleep 导致主线程阻塞,下面就来解决UI界面卡死的问题。

使用异步委托解决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();            }        }    }}

运行:

C#怎么Task执行任务

用异步方式虽然界面不会卡住,但另一个问题来了,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("线程执行完毕");    });}

运行:

C#怎么Task执行任务

效果是实现了,代码看起来好搓啊,强迫症都犯了,没关系,可以使用更优雅的写法:

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个线程执行");    });}

运行:

C#怎么Task执行任务

到此为止,功能就实现了,这个需求在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执行任务

“C#怎么Task执行任务”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯