C# 实现 异步任务自动运行控制

有这么一个场景:

假设有10000个相同逻辑的任务需要执行,而且希望是在后台异步运行;

然后在执行过程中,由于一些不确定的因素(内存、网络 等),限制了同时运行的数量(这里先假定可以同时运行50个任务);

最后关键的是,每一个任务所需的参数都不尽相同!

这就好比,有10000个工人要去做工,干的活都一样,但每个人所带的工具却不尽相同,然后又由于一些条件的限制,每次只允许50个工人在同时工作;该怎么办呢?

思路:

在现实的情况中,我们需要有一个工人调度的管理员,来随时调度这10000个带有不同工具的工人,

最开始先派上50个工人去做工,过个三五分钟就去查看一下工人的做工情况,

看了几次后,发现有20个工人已经做完了,于是就把这已经完成的20个工人撤下来,再补上新的20个工人,

又过了一段时间,发现又有15个工人做完了,于是又把这已完成的15个工人撤下来,再补上新的15个工人,

如此循环往复,只要有完成的,就撤走,换上新的...... 直到10000个工人都完成做工。

如此一来,便可以发挥最大的利用效率,总是在 允许 可做工的 范围内,拥有最多的做工人数,直到全部做工完成。

我在实际工作中的应用:

在下是做数据采集的(网络爬虫),经常会遇到这么一个情况,

发起的采集请求都是后台异步的,采集的数据有成百上千页,采集每一页的数据所发起的请求参数又不相同,然后网站又不稳定,不能同时请求太多,

于是就自己琢磨了一个功能任务自动控制类。

下面是代码,分享出来,给大家参考:

注意:看我的代码注释,帮助你理解我的实现思路,给你一个参考。

自动功能控制类:

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

namespace ConsoleAppDemo
{
    /// <summary>
    /// 自动功能控制类
    /// </summary>
    public sealed class AutoActionControl
    {
        /// <summary>
        /// AutoActionControl 无参构造函数
        /// </summary>
        public AutoActionControl() { }

        /// <summary>
        /// AutoActionControl 构造函数
        /// </summary>
        /// <param name="action">
        /// <para>Func 委托,功能函数;传入一个 object 参数,返回一个 Task 结果</para>
        /// <para>注:这个函数最好加上 try{} catch (Exception ex) { //这里可以写异常日志 }</para>
        /// </param>
        public AutoActionControl(Func<object, Task> action)
        {
            AutoAction = action;
        }

        /// <summary>
        /// AutoActionControl 构造函数
        /// </summary>
        /// <param name="action">
        /// <para>Func 委托,功能函数;传入一个 object 参数,返回一个 Task 结果</para>
        /// <para>注:这个函数最好加上 try{} catch (Exception ex) { //这里可以写异常日志 }</para>
        /// </param>
        /// <param name="paramsList">
        /// <para>参数集合 【 AutoAction 所需要的参数 】</para>
        /// <para>当 AutoAction 功能函数不需要参数时,此属性赋值为 null (也可以不用设置,默认就是 null 值)</para>
        /// <para>
        /// 当 MaxExecuteCount != 0 时(有限执行),且 AutoAction 功能函数需要参数,
        /// 此属性赋值为一个参数集合,集合的元素个数(Count 值)须等于 MaxExecuteCount
        /// </para>
        /// <para>当 MaxExecuteCount == 0 时(无限执行),此属性无意义;这种情况应当直接把“传参过程”写在 AutoAction 功能函数里</para>
        /// </param>
        public AutoActionControl(Func<object, Task> action, List<object> paramsList)
        {
            AutoAction = action;
            ParamsList = paramsList;
        }

        /// <summary>
        /// AutoActionControl 构造函数
        /// </summary>
        /// <param name="action">
        /// <para>Func 委托,功能函数;传入一个 object 参数,返回一个 Task 结果</para>
        /// <para>注:这个函数最好加上 try{} catch (Exception ex) { //这里可以写异常日志 }</para>
        /// </param>
        /// <param name="paramsList">
        /// <para>参数集合 【 AutoAction 所需要的参数 】</para>
        /// <para>当 AutoAction 功能函数不需要参数时,此属性赋值为 null (也可以不用设置,默认就是 null 值)</para>
        /// <para>
        /// 当 MaxExecuteCount != 0 时(有限执行),且 AutoAction 功能函数需要参数,
        /// 此属性赋值为一个参数集合,集合的元素个数(Count 值)须等于 MaxExecuteCount
        /// </para>
        /// <para>当 MaxExecuteCount == 0 时(无限执行),此属性无意义;这种情况应当直接把“传参过程”写在 AutoAction 功能函数里</para>
        /// </param>
        /// <param name="maxExecuteCount">
        /// <para>最大执行数量;也就是 功能函数最多运行几次</para>
        /// <para>如果设为 0,则不计总量的一直运行;属性 RunAlready 和 RunCompleted 也将没有意义。</para>
        /// </param>
        /// <param name="simultaneousExecute">同时执行数量;也就是 最多同时运行几个功能函数</param>
        /// <param name="scanningFrequency">扫描频率,单位:毫秒(每多少毫秒扫描一次)</param>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值