美文网首页.NET多线程
.NET多线程(四)任务

.NET多线程(四)任务

作者: 万州大牛 | 来源:发表于2017-03-12 19:31 被阅读0次

什么是任务?

System.Threading.Tasks.Task

任务代表一个异步操作,是未来的操作

任务非常强大,极大的简化了异步编程,并且能带来显著的性能提升,一旦你发现了她的好处,你会根本停不下来的爱上她

举个简单例子,执行一个操作,我们要查询两张表的数据,我们创建两个任务分别各自查询一张表,是不是快些呢?

任务的线程是后台线程

任务解决的问题是什么?

线程池的缺点

(1)从线程池获取结果并不方便
(2)异常处理不太方便
(3)连续的异步操作不太方便

思想的衍进

(1)线程池是对线程的抽象,让程序员不用关心线程的创建,销毁
(2)任务是对线程池的抽象,让程序员不用关心线程池线程的处理结果,异常,以及连续异步操作

怎么创建任务?

(1)构造函数

【Action 委托,Action<object>】

static void Main(string[] args)
{
    Task task = new Task(() =>
    {
        // True 线程池线程
        Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread);
    });
    task.Start();
    Console.ReadLine();
}

(2)Task.Factory.StartNew

static void Main(string[] args)
{
    Task.Factory.StartNew(() =>
    {
        // True 线程池线程
        Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread);
    });
    Console.ReadLine();
}

(3)返回结果

【Func<TResult> 委托,Func<object, TResult>】

static void Main(string[] args)
{
    Task<string> task = new Task<string>(() =>
    {
        Thread.Sleep(3 * 1000);
        // True 线程池线程
        return Thread.CurrentThread.IsThreadPoolThread.ToString();
    });
    task.Start();
    task.Wait(); // 等待任务完成
    Console.WriteLine(task.Result); // 打印结果
    Console.ReadLine();
}

(4)不使用线程池

TaskCreationOptions.LongRunning
备注
【当执行耗时操作时,如果使用线程池线程,会导致线程池线程的滥用】

static void Main(string[] args)
{
    Task task = new Task(() =>
    {
        // False 不使用线程池
        Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread);
    }, TaskCreationOptions.LongRunning);
    task.Start();
    Console.ReadLine();
}

任务內等待

(1)推荐CancallationToken.WaitHandle.WaitOne()
(2)Thread.Sleep()
(3)不建议
Thread.SpinWait(10000);

等待任务

(1)task.Wait(); 会抛内部异常
(2)Task.WaitAll(task1, task2)
一个异常,全部结束并报告异常
(3)int taskIndex = Task.WaitAny(task1, task2);
任一完成即完成,返回前有异常会报告异常

任务继续

task.ContinueWith

(1)支持1个 task 接多个ContinueWith
(2)ContinueWith返回下一代 task,下一代可以继续ContinueWith

static void Main(string[] args)
{
    Task<string> task = new Task<string>(() =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        return "girls,";
    });
    task.ContinueWith((t) =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine(t.Result + "come on.");
    });
    task.Start();
    Console.ReadLine();
}

TaskContinuationOptions

static void Main(string[] args)
{
    Task task = new Task(() =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    });
    task.ContinueWith((t) =>
    {
        Console.WriteLine("OnlyOnRanToCompletion");
    }, TaskContinuationOptions.OnlyOnRanToCompletion);
    task.Start();
    Console.ReadLine();
}

所有(任一)任务完成后继续

Task.Factory.ContineWhenAll()
Task.Factory.ContineWhenAny()
Task<TCType>.Factory.ContinueWhenAll<TAType>()
Task<TCType>.Factory.ContinueWhenAny<TAType>()

取消任务

System.Threading.CancellationTokenSource

static void Main(string[] args)
{
    CancellationTokenSource cts = new CancellationTokenSource();
    Task task = new Task(() =>
    {
        Thread.Sleep(3 * 1000);
        Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread);
    }, cts.Token);
    task.ContinueWith((t) =>
    {
        Console.WriteLine("OnlyOnCanceled");
    }, TaskContinuationOptions.OnlyOnCanceled);
    task.Start();
    //cts.Cancel();
    Console.ReadLine();
}

任务异常

无返回值,抓不到异常

try // 无返回值 try/catch 不管卵用
{
    Task task = new Task(() =>
    {
        throw new Exception("error");
    });
    task.ContinueWith((t) =>
    {
        Console.WriteLine(t.Exception.InnerException.Message);
    }, TaskContinuationOptions.OnlyOnFaulted); // 这样可以抓到异常
    task.Start();
}
catch (Exception ex)
{
    Console.WriteLine("无返回值:" + ex.Message);
}

有返回值,读取 Result

try // 有返回值,在读取 Result 时,如果任务异常,会向外抛出来
{
    Task<string> task = new Task<string>(() =>
    {
        throw new Exception("error");
        return "girls";
    });
    task.Start();
    Console.WriteLine(task.Result);
}
catch (AggregateException ex)
{
    Console.WriteLine("有返回值:" + ex.InnerException.Message);
}

任务嵌套

(1)父子任务绑定
TaskCreationOptions.AttachedToParent
父完成必须子完成,父报告子异常
(2)不绑定
我一般创建子任务,不绑定,但子任务必须处理异常并确保完成。

任务调度

System.Threading.Tasks.TaskScheduler

【默认任务调度器,使用线程池线程】

TaskScheduler.FromCurrentSynchronizationContext()

【解决在UI线程操作控件】

相关文章

  • .NET多线程(四)任务

    什么是任务? System.Threading.Tasks.Task 任务代表一个异步操作,是未来的操作 任务非常...

  • 浅谈iOS中多线程开发

    目录: (一)线程与进程之间的区别 (二)为什么需要学习多线程 (三)多线程任务执行方式 (四)多线程执行的...

  • .Net 多线程

    CPU核心数量拥有成千上万的线程,一个线程负责执行一个任务,可分为原生线程和托管线程;【寄存器 < 逻辑核心 < ...

  • Kotlin:该如何实现多线程同步?

    问题背景需执行多线程任务:任务1、任务2并行执行;等全部执行完成后,执行任务3。 实现方式「多线程同步」。Kotl...

  • 七、GCD与多线程

    队列与任务的组合 在多线程开发中我们经常会遇到这些概念:并发队列、串行队列、同步任务、异步任务。我们将这四个概念进...

  • 多线程入门

    一、多线程 1、概念: 多任务同时执行就是多线程,如果没有任务,就不需要使用多线程 线程和进程之间的区别: 进程:...

  • iOS开发中的并发、串行队列,同步、异步任务

    在多线程开发中我们经常会遇到这些概念:并发队列、串行队列、同步任务、异步任务。我们将这四个概念进行组合会有四种结果...

  • iOS - Multi-Thread

    概念篇 进程 线程 多线程 单核多线程 & 多核多线程 并行 & 并发 同步 & 异步 队列 队列 & 任务 的执...

  • Swift多线程:GCD进阶,单例、信号量、任务组

    Swift多线程:GCD进阶,单例、信号量、任务组 Swift多线程:GCD进阶,单例、信号量、任务组

  • springboot2.x 如何在请求中 多线程并发处理业务[全

    由于 我的springboot2.x 使用带返回值的异步任务实现多线程并发任务[一] 讲述了多线程处理任务,但实现...

网友评论

    本文标题:.NET多线程(四)任务

    本文链接:https://www.haomeiwen.com/subject/ecjgbttx.html