如果有些任务需要在后台自动执行,且时不时需要添加一个任务,且按照优先级顺序执行,那么可以参考本文的方法。
后台任务类
定义一个后台任务类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());