c# 后台任务自动执行

如果有些任务需要在后台自动执行,且时不时需要添加一个任务,且按照优先级顺序执行,那么可以参考本文的方法。

后台任务类

定义一个后台任务类BackgroundTaskThread,其中Start方法是用来启动任务的,循环查询是否有添加任务,外部一般就调用AppendTask来添加任务。循环任务发现任务有添加后,会自动执行。如果有多个任务,会按加入的顺序一个一个执行。

csharp 复制代码
public class BackgroundTaskThread
{
    /// <summary>
    /// 任务列表
    /// </summary>
    private List<TaskItem> TaskItems = new List<TaskItem>();
    /// <summary>
    /// 等待时间
    /// </summary>
    public int MillSeconds = 1000;
    /// <summary>
    /// 自动重置
    /// </summary>
    public AutoResetEvent TaskSet = new AutoResetEvent(false);
    /// <summary>
    /// 任务取消标识
    /// </summary>
    public CancellationTokenSource Source { get; set; } = new CancellationTokenSource();
    /// <summary>
    /// 日志
    /// </summary>
    public ILog Log { get; set; }
    /// <summary>
    /// 线程数量
    /// </summary>
    public int ThreadNum { get; private set; }
    /// <summary>
    /// 任务线程
    /// </summary>
    public List<Task> TaskThreads = new List<Task>();
    /// <summary>
    /// 启动
    /// </summary>
    /// <param name="taskTimeSpan">任务扫描间隔</param>
    /// <param name="taskNum">任务数量</param>
    public void Start(int taskTimeSpan, int taskNum)
    {
        ThreadNum = taskNum;

        for (int i = 0; i < taskNum; i++)
        {
            MillSeconds = taskTimeSpan;
            Task task = new Task(BackgroundThread);
            task.Start();
            TaskThreads.Add(task);
        }
        
    }
    /// <summary>
    /// 后台任务
    /// </summary>
    private void BackgroundThread()
    {
        try
        {
            while (!Source.Token.IsCancellationRequested)
            {
                var item = GetOrSetTaskItem(true, null);
                if(item == null)
                {
                    TaskSet.WaitOne(MillSeconds);
                }
                else
                {
                    try
                    {
                        item.Task.Invoke(item.Param);
                    }
                    catch (Exception ex)
                    {
                        Log.error("任务 : ", item.Name, " 异常停止.,..", ex);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Log.error("后台任务线程异常退出....", ex);
        }
    }

    /// <summary>
    /// 读取或者
    /// </summary>
    /// <param name="isGet">是否是获取</param>
    /// <param name="item">任务项</param>
    /// <returns></returns>
    protected TaskItem GetOrSetTaskItem(bool isGet, TaskItem item)
    {
        lock (this)
        {
            if (isGet)
            {
                if (TaskItems.Count == 0)
                    return null;
                item = TaskItems[0];
                TaskItems.RemoveAt(0);
                return item;
            }
            else
            {
                TaskItems.Add(item);
                return item;
            }
        }
    }

    /// <summary>
    /// 追加任务
    /// </summary>
    /// <param name="task"></param>
    /// <param name="param"></param>
    public void AppendTask(Action<object> task, object param)
    {
        GetOrSetTaskItem(false, new TaskItem() { Task = task, Param = param });
        TaskSet.Set();
    }
    /// <summary>
    /// 释放
    /// </summary>
    public void Dispose()
    {
        if(TaskThreads.Count > 0)
            Source.Cancel();

        TaskItems.Clear();
    }
}

实际任务

csharp 复制代码
public class DoSomethingTaskThread : BackgroundTaskThread
{
    public void AppendSomething(object data)
    {
        AppendTask(DoSomething, data);
    }
    private void DoSomething(object data)
    {
        //TODO
    }
}

外部调用

当然,最好把DoSomethingTaskThread这个子类做成单例,后面直接

csharp 复制代码
//启动任务,同步的话线程数传1,异步的话线程数可以传多点
DoSomethingTaskThread.Start(1000,1);

//添加任务
DoSomethingTaskThread.AppendSomething(new object());
相关推荐
向宇it15 分钟前
【unity组件介绍】URP Decal Projector贴花投影器,将特定材质(贴花)投影到场景中的其他对象上。
游戏·3d·unity·c#·游戏引擎·材质
斯是 陋室9 小时前
在CentOS7.9服务器上安装.NET 8.0 SDK
运维·服务器·开发语言·c++·c#·云计算·.net
inwith11 小时前
C#语法基础总结(超级全面)(二)
开发语言·c#
ヾChen15 小时前
13届蓝桥杯省赛程序设计试题
物联网·学习·蓝桥杯·c#
我是唐青枫19 小时前
C#.NET 泛型详解
开发语言·c#·.net
Yasin Chen19 小时前
C# StringBuilder源码分析
开发语言·c#
格林威21 小时前
Baumer工业相机堡盟工业相机如何通过YoloV8模型实现人物识别(C#)
开发语言·人工智能·数码相机·yolo·计算机视觉·c#
Rabbb21 小时前
C# JSON 反序列化时,忽略转换失败的属性 JTokenSafeToExtensions
后端·c#·json
三目条件21 小时前
C#将类属性保存到Ini文件方法(利用拓展方法,反射方式获取到分组名和属性名称属性值)
java·开发语言·c#
啊基米德1 天前
lua(xlua)基础知识点记录二
c#·lua·xlua