C#多线程系列之工作流实现

目录
  • 前言
  • 节点
    • Then
    • Parallel
    • Schedule
    • Delay
  • 试用一下
    • 顺序节点
    • 并行任务
  • 编写工作流
    • 接口构建器
    • 工作流构建器
    • 依赖注入
    • 实现工作流解析

前言

前面学习了很多多线程和任务的基础知识,这里要来实践一下啦。通过本篇教程,你可以写出一个简单的工作流引擎。

本篇教程内容完成是基于任务的,只需要看过笔者的三篇关于异步的文章,掌握 C# 基础,即可轻松完成。

  • C#多线程系列之任务基础(一)
  • C#多线程系列之任务基础(二)
  • C#多线程系列之任务基础(三)

由于本篇文章编写的工作流程序,主要使用任务,有些逻辑过程会比较难理解,多测试一下就好。代码主要还是 C# 基础,为什么说简单?

  • 不包含 async 、await
  • 几乎不含包含多线程(有个读写锁)
  • 不包含表达式树
  • 几乎不含反射(有个小地方需要反射一下,但是非常简单)
  • 没有复杂的算法

因为是基于任务(Task)的,所以可以轻松设计组合流程,组成复杂的工作流。

由于只是讲述基础,所以不会包含很多种流程控制,这里只实现一些简单的。

先说明,别用到业务上。。。这个工作流非常简单,就几个功能,这个工作流是基于笔者的多线程系列文章的知识点。写这个东西是为了讲解任务操作,让读者更加深入理解任务。

代码地址:https://github.com/whuanle/CZGL.FLow

节点

在开始前,我们来设计几种流程控制的东西。

将一个 步骤/流程/节点 称为 step。

Then

一个普通的节点,包含一个任务。

多个 Then 节点,可以组成一条连续的工作流。

Parallel

并行节点,可以设置多个并行节点放到 Parallel 中,以及在里面为任一个节点创建新的分支。

Schedule

定时节点,创建后会在一定时间后执行节点中的任务。

Delay

让当前任务阻塞一段时间。

试用一下

顺序节点

打开你的 VS ,创建项目,Nuget 引用 CZGL.DoFlow ,版本 1.0.2 。

创建一个类 MyFlow1,继承 IDoFlow

    public class MyFlow1 : IDoFlow
    {
        public int Id => 1;

        public string Name => "随便起个名字";

        public int Version => 1;

        public IDoFlowBuilder Build(IDoFlowBuilder builder)
        {
            throw new NotImplementedException();
        }
    }

你可以创建多个工作流任务,每个工作流的 Id 必须唯一。Name 和 Version 随便填,因为这里笔者没有对这几个字段做逻辑。

IDoFlowBuilder 是构建工作流的一个接口。

我们来写一个工作流测试一下。

/// <summary>
/// 普通节点 Then 使用方法
/// </summary>
public class MyFlow1 : IDoFlow
{
    public int Id => 1;
    public string Name => "test";
    public int Version => 1;

    public IDoFlowBuilder Build(IDoFlowBuilder builder)
    {
        builder.StartWith(() =>
        {
            Console.WriteLine("工作流开始");
        }).Then(() =>
        {
            Console.WriteLine("下一个节点");
        }).Then(() =>
         {
             Console.WriteLine("最后一个节点");
         });
        return builder;
    }
} 

Main 方法中:

        static void Main(string[] args)
        {
            FlowCore.RegisterWorkflow<MyFlow1>();
            // FlowCore.RegisterWorkflow(new MyFlow1());
            FlowCore.Start(1);
            Console.ReadKey();
        }

.StartWith() 方法开始一个工作流;

FlowCore.RegisterWorkflow<T>() 注册一个工作流;

FlowCore.Start();执行一个工作流;

并行任务

其代码如下:

    /// <summary>
    /// 并行节点 Parallel 使用方法
    /// </summary>
    public class MyFlow2 : IDoFlow
    {
        public int Id => 2;
        public string Name => "test";
        public int Version => 1;

        public IDoFlowBuilder Build(IDoFlowBuilder builder)
        {
            builder.StartWith()
                .Parallel(steps =>
                {
                    // 每个并行任务也可以设计后面继续执行其它任务
                    steps.Do(() =>
                    {
                        Console.WriteLine("并行1");
                    }).Do(() =>
                    {
                        Console.WriteLine("并行2");
                    });
                    steps.Do(() =>
                    {
                        Console.WriteLine("并行3");
                    });

                    // 并行任务设计完成后,必须调用此方法
                    // 此方法必须放在所有并行任务 .Do() 的最后
                    steps.EndParallel();

                    // 如果 .Do() 在 EndParallel() 后,那么不会等待此任务
                    steps.Do(() => { Console.WriteLine("并行异步"); });

                    // 开启新的分支
                    steps.StartWith()
                    .Then(() =>
                    {
                        Console.WriteLine("新的分支" + Task.CurrentId);
                    }).Then(() => { Console.WriteLine("分支2.0" + Task.CurrentId); });

                }, false)
                .Then(() =>
                {
                    Console.WriteLine("11111111111111111 ");
                });

            return builder;
        }
    }

Main 方法中:

        static void Main(string[] args)
        {
            FlowCore.RegisterWorkflow<MyFlow2>();
            FlowCore.Start(2);
            Console.ReadKey();
        }

通过以上示例,可以大概了解本篇文章中我们要写的程序。

编写工作流

建立一个类库项目,名为 DoFlow

建立 ExtensionsInterfacesServices 三个目录。

接口构建器

新建 IStepBuilder 接口文件到 Interfaces 目录,其内容如下:

using System;

namespace DoFlow.Interfaces
{
    public interface IStepBuilder
    {
        /// <summary>
        /// 普通节点
        /// </summary>
        /// <param name="stepBuilder"></param>
        /// <returns></returns>
        IStepBuilder Then(Action action);

        /// <summary>
        /// 多个节点
        /// <para>默认下,需要等待所有的任务完成,这个step才算完成</para>
        /// </summary>
        /// <param name="action"></param>
        /// <param name="anyWait">任意一个任务完成即可跳转到下一个step</param>
        /// <returns></returns>
        IStepBuilder Parallel(Action<IStepParallel> action, bool anyWait = false);

        /// <summary>
        /// 节点将在某个时间间隔后执行
        /// <para>异步,不会阻塞当前工作流的运行,计划任务将在一段时间后触发</para>
        /// </summary>
        /// <returns></returns>
        IStepBuilder Schedule(Action action, TimeSpan time);

        /// <summary>
        /// 阻塞一段时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        IStepBuilder Delay(TimeSpan time);
    }
}

新建 IStepParallel 文件到 Interfaces 目录。

using System;

namespace DoFlow.Interfaces
{
    /// <summary>
    /// 并行任务
    ///  <para>默认情况下,只有这个节点的所有并行任务都完成后,这个节点才算完成</para>
    /// </summary>
    public interface IStepParallel
    {
        /// <summary>
        /// 一个并行任务
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        IStepParallel Do(Action action);

        /// <summary>
        /// 开始一个分支
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        IStepBuilder StartWith(Action action = null);

        /// <summary>
        /// 必须使用此方法结束一个并行任务
        /// </summary>
        void EndParallel();
    }

    /// <summary>
    /// 并行任务
    /// <para>任意一个任务完成后,就可以跳转到下一个 step</para>
    /// </summary>
    public interface IStepParallelAny : IStepParallel
    {

    }
}

工作流构建器

新建 IDoFlowBuilder 接口文件到 Interfaces 目录。

using System;
using System.Threading.Tasks;

namespace DoFlow.Interfaces
{
    /// <summary>
    /// 构建工作流任务
    /// </summary>
    public interface IDoFlowBuilder
    {
        /// <summary>
        /// 开始一个 step
        /// </summary>
        IStepBuilder StartWith(Action action = null);
        void EndWith(Action action);

        Task ThatTask { get; }
    }
}

新建 IDoFlow 接口文件到 Interfaces 目录。

namespace DoFlow.Interfaces
{

    /// <summary>
    /// 工作流
    /// <para>无参数传递</para>
    /// </summary>
    public interface IDoFlow
    {
        /// <summary>
        /// 全局唯一标识
        /// </summary>
        int Id { get; }

        /// <summary>
        /// 标识此工作流的名称
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 标识此工作流的版本
        /// </summary>
        int Version { get; }

        IDoFlowBuilder Build(IDoFlowBuilder builder);
    }
}

依赖注入

新建 DependencyInjectionService 文件到 Services 目录。

用于实现依赖注入和解耦。

using DoFlow.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace DoFlow.Services
{
    /// <summary>
    /// 依赖注入服务
    /// </summary>
    public static class DependencyInjectionService
    {
        private static IServiceCollection _servicesList;
        private static IServiceProvider _services;
        static DependencyInjectionService()
        {
            IServiceCollection services = new ServiceCollection();
            _servicesList = services;
            // 注入引擎需要的服务
            InitExtension.StartInitExtension();
            var serviceProvider = services.BuildServiceProvider();
            _services = serviceProvider;
        }

        /// <summary>
        /// 添加一个注入到容器服务
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        public static void AddService<TService, TImplementation>()
            where TService : class
            where TImplementation : class, TService
        {
            _servicesList.AddTransient<TService, TImplementation>();
        }

        /// <summary>
        /// 获取需要的服务
        /// </summary>
        /// <typeparam name="TIResult"></typeparam>
        /// <returns></returns>
        public static TIResult GetService<TIResult>()
        {
            TIResult Tservice = _services.GetService<TIResult>();
            return Tservice;
        }
    }
}

添加一个 InitExtension 文件到 Extensions 目录。

using DoFlow.Interfaces;
using DoFlow.Services;

namespace DoFlow.Extensions
{
    public static class InitExtension
    {
        private static bool IsInit = false;
        public static void StartInitExtension()
        {
            if (IsInit) return;
            IsInit = true;
            DependencyInjectionService.AddService<IStepBuilder, StepBuilder>();
            DependencyInjectionService.AddService<IDoFlowBuilder, DoFlowBuilder>();
            DependencyInjectionService.AddService<IStepParallel, StepParallelWhenAll>();
            DependencyInjectionService.AddService<IStepParallelAny, StepParallelWhenAny>();
        }
    }
}

实现工作流解析

以下文件均在 Services 目录建立。

新建 StepBuilder 文件,用于解析节点,构建任务。

using DoFlow.Interfaces;
using System;
using System.Threading.Tasks;

namespace DoFlow.Services
{

    /// <summary>
    /// 节点工作引擎
    /// </summary>
    public class StepBuilder : IStepBuilder
    {
        private Task _task;

        /// <summary>
        /// 延迟执行
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public IStepBuilder Delay(TimeSpan time)
        {
            Task.Delay(time).Wait();
            return this;
        }

        /// <summary>
        /// 并行 step
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public IStepBuilder Parallel(Action<IStepParallel> action, bool anyAwait = false)
        {
            IStepParallel parallel = anyAwait ? DependencyInjectionService.GetService<IStepParallelAny>() : DependencyInjectionService.GetService<IStepParallel>();
            Task task = new Task(() =>
            {
                action.Invoke(parallel);
            });

            _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() =>
            {
                task.Start();
            });
            _task = task;
            return this;
        }

        /// <summary>
        /// 计划任务
        /// </summary>
        /// <param name="action"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        public IStepBuilder Schedule(Action action, TimeSpan time)
        {
            Task.Factory.StartNew(() =>
            {
                Task.Delay(time).Wait();
                action.Invoke();
            });
            return this;
        }

        /// <summary>
        /// 普通 step
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public IStepBuilder Then(Action action)
        {
            Task task = new Task(action);
            _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() =>
            {
                task.Start();
                task.Wait();
            });
            _task = task;
            return this;
        }

        public void SetTask(Task task)
        {
            _task = task;
        }
    }
}

新建 StepParallel 文件,里面有两个类,用于实现同步任务。

using DoFlow.Interfaces;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace DoFlow.Services
{
    /// <summary>
    /// 第一层所有任务结束后才能跳转下一个 step
    /// </summary>
    public class StepParallelWhenAll : IStepParallel
    {
        private Task _task;
        private readonly List<Task> _tasks = new List<Task>();
        public StepParallelWhenAll()
        {
            _task = new Task(() => { },TaskCreationOptions.AttachedToParent);
        }
        public IStepParallel Do(Action action)
        {
            _tasks.Add(Task.Run(action));
            return this;
        }

        public void EndParallel()
        {
            _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() =>
            {
                Task.WhenAll(_tasks).Wait();
            });
        }

        public IStepBuilder StartWith(Action action = null)
        {
            Task task =
                action is null ? new Task(() => { })
                : new Task(action);
            var _stepBuilder = DependencyInjectionService.GetService<IStepBuilder>();
            _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() => { task.Start(); });

            return _stepBuilder;
        }
    }

    /// <summary>
    /// 完成任意一个任务即可跳转到下一个 step
    /// </summary>
    public class StepParallelWhenAny : IStepParallelAny
    {
        private Task _task;
        private readonly List<Task> _tasks = new List<Task>();
        public StepParallelWhenAny()
        {
            _task = Task.Run(() => { });
        }
        public IStepParallel Do(Action action)
        {
            _tasks.Add(Task.Run(action));
            return this;
        }

        public void EndParallel()
        {
            _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() =>
            {
                Task.WhenAny(_tasks).Wait();
            });
        }

        public IStepBuilder StartWith(Action action = null)
        {
            Task task =
                action is null ? new Task(() => { })
                : new Task(action);
            var _stepBuilder = DependencyInjectionService.GetService<IStepBuilder>();
            _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() => { task.Start(); });

            return _stepBuilder;
        }
    }
}

新建 DoFlowBuilder 文件,用于构建工作流。

using DoFlow.Interfaces;
using System;
using System.Threading.Tasks;

namespace DoFlow.Services
{
    public class DoFlowBuilder : IDoFlowBuilder
    {
        private Task _task;
        public Task ThatTask => _task;

        public void EndWith(Action action)
        {
            _task.Start();
        }

        public IStepBuilder StartWith(Action action = null)
        {
            if (action is null)
                _task = new Task(() => { });
            else _task = new Task(action);

            IStepBuilder _stepBuilder = DependencyInjectionService.GetService<IStepBuilder>();
            ((StepBuilder)_stepBuilder).SetTask(_task);
            return _stepBuilder;
        }
    }
}

新建 FlowEngine 文件,用于执行工作流。

using DoFlow.Interfaces;

namespace DoFlow.Services
{
    /// <summary>
    /// 工作流引擎
    /// </summary>
    public class FlowEngine
    {
        private readonly IDoFlow _flow;
        public FlowEngine(IDoFlow flow)
        {
            _flow = flow;
        }

        /// <summary>
        /// 开始一个工作流
        /// </summary>
        public void Start()
        {
            IDoFlowBuilder builder = DependencyInjectionService.GetService<IDoFlowBuilder>();
            _flow.Build(builder).ThatTask.Start();
        }
    }
}

新建 FlowCore 文件,用于存储和索引工作流。使用读写锁解决并发字典问题。

using DoFlow.Interfaces;
using System;
using System.Collections.Generic;
using System.Threading;

namespace DoFlow.Services
{
    public static class FlowCore
    {
        private static Dictionary<int, FlowEngine> flowEngines = new Dictionary<int, FlowEngine>();

        // 读写锁
        private static ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim();

        /// <summary>
        /// 注册工作流
        /// </summary>
        /// <param name="flow"></param>
        public static bool RegisterWorkflow(IDoFlow flow)
        {
            try
            {
                readerWriterLockSlim.EnterReadLock();
                if (flowEngines.ContainsKey(flow.Id))
                    return false;
                flowEngines.Add(flow.Id, new FlowEngine(flow));
                return true;
            }
            finally
            {
                readerWriterLockSlim.ExitReadLock();
            }
        }

        /// <summary>
        /// 注册工作流
        /// </summary>
        /// <param name="flow"></param>
        public static bool RegisterWorkflow<TDoFlow>()
        {

            Type type = typeof(TDoFlow);
            IDoFlow flow = (IDoFlow)Activator.CreateInstance(type);
            try
            {
                readerWriterLockSlim.EnterReadLock();
                if (flowEngines.ContainsKey(flow.Id))
                    return false;
                flowEngines.Add(flow.Id, new FlowEngine(flow));
                return true;
            }
            finally
            {
                readerWriterLockSlim.ExitReadLock();
            }
        }

        /// <summary>
        /// 要启动的工作流
        /// </summary>
        /// <param name="id"></param>
        public static bool Start(int id)
        {
            FlowEngine engine;
            // 读写锁
            try
            {
                readerWriterLockSlim.EnterUpgradeableReadLock();

                if (!flowEngines.ContainsKey(id))
                    return default;
                try
                {
                    readerWriterLockSlim.EnterWriteLock();
                    engine = flowEngines[id];
                }
                catch { return default; }
                finally
                {
                    readerWriterLockSlim.ExitWriteLock();
                }
            }
            catch { return default; }
            finally
            {
                readerWriterLockSlim.ExitUpgradeableReadLock();
            }

            engine.Start();
            return true;
        }
    }
}

就这样程序写完了。

到此这篇关于C#多线程系列之工作流实现的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#多线程系列之线程池

    目录 线程池 ThreadPool 常用属性和方法 线程池说明和示例 线程池线程数 线程池线程数说明 不支持的线程池异步委托 任务取消功能 计时器 线程池 线程池全称为托管线程池,线程池受 .NET 通用语言运行时(CLR)管理,线程的生命周期由 CLR 处理,因此我们可以专注于实现任务,而不需要理会线程管理. 线程池的应用场景:任务并行库 (TPL)操作.异步 I/O 完成.计时器回调.注册的等待操作.使用委托的异步方法调用和套接字连接. 很多人不清楚 Task.Task<TResult>

  • C#多线程系列之读写锁

    本篇的内容主要是介绍 ReaderWriterLockSlim 类,来实现多线程下的读写分离. ReaderWriterLockSlim ReaderWriterLock 类:定义支持单个写线程和多个读线程的锁. ReaderWriterLockSlim 类:表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问. 两者的 API 十分接近,而且 ReaderWriterLockSlim 相对 ReaderWriterLock 来说 更加安全.因此本文主要讲解 ReaderWrit

  • C#多线程系列之进程同步Mutex类

    Mutex 中文为互斥,Mutex 类叫做互斥锁.它还可用于进程间同步的同步基元. Mutex 跟 lock 相似,但是 Mutex 支持多个进程.Mutex 大约比 lock 慢 20 倍. 互斥锁(Mutex),用于多线程中防止两条线程同时对一个公共资源进行读写的机制. Windows 操作系统中,Mutex 同步对象有两个状态: signaled:未被任何对象拥有: nonsignaled:被一个线程拥有: Mutex 只能在获得锁的线程中,释放锁. 构造函数和方法 Mutex 类其构造函

  • C#多线程系列之线程的创建和生命周期

    目录 1,获取当前线程信息 2,管理线程状态 2.1 启动与参数传递 2.1.1 ParameterizedThreadStart 2.1.2 使用静态变量或类成员变量 2.1.3 委托与Lambda 2.2 暂停与阻塞 2.3 线程状态 2.4 终止 2.5 线程的不确定性 2.6 线程优先级.前台线程和后台线程 2.7 自旋和休眠 1,获取当前线程信息 Thread.CurrentThread 是一个 静态的 Thread 类,Thread 的CurrentThread 属性,可以获取到当前

  • C#多线程系列之线程通知

    AutoRestEvent 类用于从一个线程向另一个线程发送通知. 微软文档是这样介绍的:表示线程同步事件在一个等待线程释放后收到信号时自动重置. 其构造函数只有一个: 构造函数里面的参数用于设置信号状态. 构造函数 说明 AutoResetEvent(Boolean) 用一个指示是否将初始状态设置为终止的布尔值初始化 AutoResetEvent 类的新实例. 真糟糕的机器翻译. 常用方法 AutoRestEvent 类是干嘛的,构造函数的参数又是干嘛的?不着急,我们来先来看看这个类常用的方法

  • C#多线程系列之原子操作

    目录 知识点 竞争条件 线程同步 CPU时间片和上下文切换 阻塞 内核模式和用户模式 Interlocked 类 1,出现问题 2,Interlocked.Increment() 3,Interlocked.Exchange() 4,Interlocked.CompareExchange() 5,Interlocked.Add() 6,Interlocked.Read() 知识点 竞争条件 当两个或两个以上的线程访问共享数据,并且尝试同时改变它时,就发生争用的情况.它们所依赖的那部分共享数据,叫

  • C#多线程系列之多线程锁lock和Monitor

    目录 1,Lock lock 原型 lock 编写实例 2,Monitor 怎么用呢 解释一下 示例 设置获取锁的时效 1,Lock lock 用于读一个引用类型进行加锁,同一时刻内只有一个线程能够访问此对象.lock 是语法糖,是通过 Monitor 来实现的. Lock 锁定的对象,应该是静态的引用类型(字符串除外). 实际上字符串也可以作为锁的对象使用,只是由于字符串对象的特殊性,可能会造成不同位置的不同线程冲突.如果你能保证字符串的唯一性,例如 Guid 生成的字符串,也是可以作为锁的对

  • C#多线程系列之任务基础(二)

    目录 判断任务状态 再说父子任务 组合任务/延续任务 复杂的延续任务 并行(异步)处理任务 并行(同步)处理任务 并行任务的 Task.WhenAny 并行任务状态 循环中值变化问题 定时任务 TaskScheduler 类 判断任务状态 属性 说明 IsCanceled 获取此 Task 实例是否由于被取消的原因而已完成执行. IsCompleted 获取一个值,它表示是否已完成任务. IsCompletedSuccessfully 了解任务是否运行到完成. IsFaulted 获取 Task

  • C#多线程系列之线程等待

    目录 前言 volatile 关键字 三种常用等待 再说自旋和阻塞 SpinWait 结构 属性和方法 自旋示例 新的实现 SpinLock 结构 属性和方法 示例 等待性能对比 前言 volatile 关键字 volatile 关键字指示一个字段可以由多个同时执行的线程修改. 我们继续使用<C#多线程(3):原子操作>中的示例: static void Main(string[] args) { for (int i = 0; i < 5; i++) { new Thread(AddO

  • C#多线程系列之手动线程通知

    区别与示例 AutoResetEvent 和 ManualResetEvent 十分相似.两者之间的区别,在于前者是自动(Auto),后者是手动(Manua). 你可以先运行下面的示例,再测试两者的区别. AutoResetEvent 示例: class Program { // 线程通知 private static AutoResetEvent resetEvent = new AutoResetEvent(false); static void Main(string[] args) {

  • C#多线程系列之多阶段并行线程

    前言 这一篇,我们将学习用于实现并行任务.使得多个线程有序同步完成多个阶段的任务. 应用场景主要是控制 N 个线程(可随时增加或减少执行的线程),使得多线程在能够在 M 个阶段中保持同步. 线程工作情况如下: 我们接下来 将学习C# 中的 Barrier ,用于实现并行协同工作. Barrier 类 使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作,使多个线程(称为“参与者” )分阶段同时处理算法. 可以使多个线程(称为“参与者” )分阶段同时处理算法.(注意算法这个词) 每个参与者完

  • C#多线程系列之线程完成数

    解决一个问题 假如,程序需要向一个 Web 发送 5 次请求,受网路波动影响,有一定几率请求失败.如果失败了,就需要重试. 示例代码如下: class Program { private static int count = 0; static void Main(string[] args) { for (int i = 0; i < 5; i++) new Thread(HttpRequest).Start(); // 创建线程 // 用于不断向另一个线程发送信号 while (count

  • C#多线程系列之任务基础(一)

    目录 多线程编程 多线程编程模式 探究优点 任务操作 两种创建任务的方式 Task.Run() 创建任务 取消任务 父子任务 任务返回结果以及异步获取返回结果 捕获任务异常 全局捕获任务异常 多线程编程 多线程编程模式 .NET 中,有三种异步编程模式,分别是基于任务的异步模式(TAP).基于事件的异步模式(EAP).异步编程模式(APM). 基于任务的异步模式 (TAP) :.NET 推荐使用的异步编程方法,该模式使用单一方法表示异步操作的开始和完成.包括我们常用的 async .await

  • C#多线程系列之任务基础(三)

    目录 TaskAwaiter 延续的另一种方法 另一种创建任务的方法 实现一个支持同步和异步任务的类型 Task.FromCanceled() 如何在内部取消任务 Yield 关键字 补充知识点 TaskAwaiter 先说一下 TaskAwaiter,TaskAwaiter 表示等待异步任务完成的对象并为结果提供参数. Task 有个 GetAwaiter() 方法,会返回TaskAwaiter 或TaskAwaiter<TResult>,TaskAwaiter 类型在 System.Run

  • C#多线程系列之资源池限制

    Semaphore.SemaphoreSlim 类 两者都可以限制同时访问某一资源或资源池的线程数. 这里先不扯理论,我们从案例入手,通过示例代码,慢慢深入了解. Semaphore 类 这里,先列出 Semaphore 类常用的 API. 其构造函数如下: 构造函数 说明 Semaphore(Int32, Int32) 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数. Semaphore(Int32, Int32, String) 初始化 Semaphore 类的新实

随机推荐