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());
相关推荐
逝水无殇6 小时前
C# 异常处理详解
开发语言·后端·c#
玖玥拾8 小时前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
逝水无殇9 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
唐青枫14 小时前
看懂 IL 的关键:C#.NET 栈机执行模型实战拆解
c#·.net
我才是银古14 小时前
从零构建 Windows 桌面 RPA 框架:Go 与 .NET 的跨语言协奏
c#·go·rpa
逝水无殇16 小时前
C# 正则表达式详解
开发语言·后端·正则表达式·c#
朱永博16 小时前
使用Onnruntime实现Padim/Patchcore推理
开发语言·c#
吴可可12318 小时前
C# CAD二次开发添加带按钮的窗口
c#
铅笔侠_小龙虾19 小时前
Rust 学习(8)-切片类型
学习·rust·c#
习明然1 天前
我的本地化AI项目(三)
人工智能·python·electron·c#·avalonia