C# Task 用法

转自原文 C# Task 用法

C# Task 的用法

其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观。代码更简洁了,使用Task来进行操作。可以跟线程一样可以轻松的对执行的方法进行控制。

顺便提一下,配合CancellationTokenSource类更为可以轻松的对Task操作的代码进行中途终止运行,会在后面的章节中讲述。

如果我们使用线程池来实现某几个方法运行,然后等待运行完成的大概会编写如下代码:

    using (ManualResetEvent m1 = new ManualResetEvent(false))
    using (ManualResetEvent m2 = new ManualResetEvent(false))
    {
        ThreadPool.QueueUserWorkItem(delegate
        {
            MyMethodA();
            m1.Set();
        });
        ThreadPool.QueueUserWorkItem(delegate
        {
            MyMethodB();
            m2.Set();
        });
        WaitHandle.WaitAll(new WaitHandle[] { m1, m2, });
    }

如果用Task类的话,相对就比较简单了,至少代码看起来很舒服。也就意味着维护也比较方便

    Task t1 = Task.Factory.StartNew(delegate { MyMethodA(); });
    Task t2 = Task.Factory.StartNew(delegate { MyMethodB(); });
    t1.Wait();
    t2.Wait();

上面的方法是一个一个的执行完毕,获取不是我们想要的,我们一般是想要他们一起同时执行,提高程序处理事情的效率。

    Task t1 = Task.Factory.StartNew(delegate { MyMethodA(); });
    Task t2 = Task.Factory.StartNew(delegate { MyMethodB(); });
    Task.WaitAll(t1, t2);

下面我们来简单介绍下Task的用法

创建 Task

创建Task有两种方式,一种是使用构造函数创建,另一种是使用 Task.Factory.StartNew 进行创建。如下代码所示

1.使用构造函数创建Task

  1. Task t1 = new Task(MyMethod);

2.使用Task.Factory.StartNew 进行创建Task

  1. Task t1 = Task.Factory.StartNew(MyMethod);

其实这两种方式都是一样的,Task.Factory 是对Task进行管理,调度管理这一类的。好学的伙伴们,可以深入研究。这不是本文的范畴,也许会在后面的文章细说。

运行 Task

运行Task的两种方式,在上面我们已经提到过了,一种等待运行完毕,另一种则等待所有运行完毕。不过这里还有一种就是异步运行跟使用多线程一样,调用Task对象中的Start()方法即可。看看下面这个控制台示例。纯粹是Wait和AllWait的话,仅仅是等待。而不是执行。所以我们还需要调用Start()方法

    static void Main(string[] args)
    {
        Task t1 = new Task(MyMethod);
        t1.Start();
        Console.WriteLine("主线程代码运行结束");
        Console.ReadLine();
    }

    static void MyMethod()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine(DateTime.Now.ToString());
            Thread.Sleep(1000);
        }
    }

运行效果如图

因为我们没有调用Wait 所以是异步执行的~

取消Task

我们一开始就描述了 CancellationTokenSource 这个对象对Task的取消运行。一般是用不到这个方法的,一般会正常的退出所运行的代码,如使用 bool IsExit 之类的来进行一个控制。而不是中途强制中断代码。

可以参考我的这篇文章:http://www.wxzzz.com/643.html

至于 CancellationTokenSource 控制Task,下一篇文章会进行详细的一个介绍。

Task的异常处理

因为Task中是异步执行,你也可以理解为跟多线程一样,具体错误捕获需要自己去捕获。很有意思的是Task的异常还会重新抛到Wait和AllWait中,我们可以进行方便的捕获这些异常。如下代码

    static void Main(string[] args)
    {
        Task t1 = new Task(MyMethod);
        t1.Start();
        t1.Wait();
        Console.WriteLine("主线程代码运行结束");
        Console.ReadLine();
    }

    static void MyMethod()
    {
        throw new Exception("Task异常测试");
    }

运行效果如图

获取 Task 的返回值

先看看代码

    Task<string> t1 = Task.Factory.StartNew(() => "测试");
    t1.Wait();
    Console.WriteLine(t1.Result);
    Console.ReadLine();

返回值可以是任意的类型,因为是个泛型嘛~ 还是依然的非常简洁的代码。

时间: 2024-10-06 08:31:49

C# Task 用法的相关文章

C# task用法

C# Task 的用法 其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观.代码更简洁了,使用Task来进行操作.可以跟线程一样可以轻松的对执行的方法进行控制. 顺便提一下,配合CancellationTokenSource类更为可以轻松的对Task操作的代码进行中途终止运行. 创建Task 创建Task有两种方式,一种是使用构造函数创建,另一种是使用 Task.Factory.StartNew 进行创建.如下代码所示 1.使用构造函数创建Task  Task t1 =

Task用法(2)-任务等待wait

1.Wait 用法 默认情况下,Task 是有线程池中的异步线程执行,是否执行完成,可以通过Task的的属性IsCompleted 来判断, 如果想在子线程工作完成之后,在进行后续主线程工作可以通过调用task.Wait() 来等待线程完成,调用Wait 后,当前线程会被阻塞,直到到子线程完成. 代码示例: static void Main(string[] args) { Task t = Task.Run(() => { Thread.Sleep(500); Console.WriteLin

SSIS Execute SQL Task 用法

Execute Sql Task组件是一个非常有用的Control Flow Task,可以直接执行SQL语句,例如,可以执行数据更新命令(update,delete,insert),也可以执行select查询语句,返回结果集,结果集可以是一行,也可以是多行. 一,General 选项卡 1,返回结果集(Result Set) None:表示不返回结果,在执行Update,delete或insert命令时,使用该选项: Single row:返回单行结果,可以在Result Set 选项卡中,将

c#, Task用法说明

1. C# Task 的用法 http://www.wxzzz.com/683.html C# 多线程的自动管理(线程池) http://www.cnblogs.com/SkySoot/archive/2012/04/01/2429259.html .Net项目分层与文件夹结构大全 http://www.wxzzz.com/1354.html

verilog中的task用法

任务就是一段封装在“task-endtask”之间的程序.任务是通过调用来执行的,而且只有在调用时才执行,如果定义了任务,但是在整个过程中都没有调用它,那么这个任务是不会执行的.调用某个任务时可能需要它处理某些数据并返回操作结果,所以任务应当有接收数据的输入端和返回数据的输出端.另外,任务可以彼此调用,而且任务内还可以调用函数.  1.任务定义 任务定义的形式如下: task task_id;     [declaration]     procedural_statement endtask 

终于明白了 C# 中 Task.Yield 的用途

最近在阅读 .NET Threadpool starvation, and how queuing makes it worse 这篇博文时发现文中代码中的一种 Task 用法之前从未见过,在网上看了一些资料后也是云里雾里不知其解,很是困扰.今天在程序员节的大好日子里终于想通了,于是写下这篇随笔分享给大家,也过过专心写博客的瘾. 这种从未见过的用法就是下面代码中的 await Task.Yield() : static async Task Process() { await Task.Yiel

dos 与 进程

第一步:netstat -ano 查询当前开发的进程pid 第二步:dos中关闭程序的命令有很多,比如wmic.taskkill等,taskkill是其中最常用的一种(wmic也很强的),task用法是 taskkill /f /im 进程名,或者taskkill /f PID,比如qq的进程qq.exe.直接taskkill /f /im ttplayer.exe ,如果它的pid是8089就taskkill /f PID 8090  

Parallel与PLINQ简单示例

Parallel是对Task用法的简化,含有Parallel.For.Parallel.ForEach.Parallel.Invoke三个静态方法.PLINQ是并行版本的LINQ.下面给出Parallel和PLINQ的简单示例及注意事项. 一.简单示例 1.Parallel.For int[] nums = new[] { 1, 2, 3, 4 }; Parallel.For(0, nums.Length, i => { Console.WriteLine("下标:{0},值:{1}&qu

使用FluentMigrator进行数据库迁移

介绍 在开发的过程中,经常会遇到数据库结构变动(表新增.删除,表列新增.修改.删除等).开发环境.测试环境.正式环境都要记性同步:如果你使用EF有自动迁移的功能,还是挺方便的.如果非EF我们需要手工处理,有时候会忘记,繁琐.恰好 网上有提供的工具来实现类似EF的迁移功能.如:SQL Server Data Tools.Fluent Migrator.RoundhousE. DbUp.Conclusion:本文将着重分享下如何使用Fluent Migrator进行数据库迁移. Fluent Mig