个人封装的常用的功能类,感觉可以分享一波。
c# 批量任务队列
在实际项目中,需要批量处理一定数量的队列数据,而不是,一个一个处理,来提高效率。.
但是,默认是不支持的。这个时候,就需要这样的一个业务逻辑对象。
/// <summary>
/// 任务队列接口
/// </summary>
public interface ITaskQueue<T>
{
/// <summary>
/// 增加一个对象
/// </summary>
/// <param name="t"></param>
void Add(T t);
/// <summary>
/// 获取一个分组队列
/// </summary>
/// <returns></returns>
IList<T> GetQueue();
/// <summary>
/// 是否阻塞增加
/// </summary>
/// <returns></returns>
bool IsWaitAdd();
/// <summary>
/// 当前队列完成
/// </summary>
void Complete();
}
/// <summary>
/// 任务队列
/// </summary>
public class TaskQueue<T> : ITaskQueue<T>, IDisposable
{
/// <summary>
/// 内置队列
/// </summary>
private ConcurrentDictionary<int, IList<T>> taskQueues;
/// <summary>
/// 分区大小
/// </summary>
private int PartitionSize;
/// <summary>
/// 默认index为0
/// </summary>
private int Index = 0;
/// <summary>
/// 默认处理偏移
/// </summary>
private int OffSet = 0;
/// <summary>
/// 内置锁
/// </summary>
private object Lock = new object();
/// <summary>
/// <summary>
/// 构造
/// </summary>
/// <param name="PartitionSize">分区大小,默认分区大小为10 </param>
public TaskQueue(int PartitionSize = 10)
{
taskQueues = new ConcurrentDictionary<int, IList<T>>();
this.PartitionSize = PartitionSize;
List<T> ts = new List<T>();
taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
}
/// <summary>
/// 增加一个对象
/// </summary>
/// <param name="t"></param>
public void Add(T t)
{
lock (Lock)
{
IList<T> ts;
if (taskQueues.TryGetValue(Index, out ts))
{
if (ts.Count < PartitionSize)
{
ts.Add(t);
taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
}
else //超出区域范围,则新建区
{
Index++;
IList<T> ts1 = new List<T>();
ts1.Add(t);
taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
}
}
else
{
IList<T> ts1 = new List<T>();
ts1.Add(t);
taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
}
}
}
/// <summary>
/// 获取一个分组队列
/// </summary>
/// <returns></returns>
public IList<T> GetQueue()
{
lock (Lock)
{
IList<T> ts;
if (taskQueues.TryGetValue(OffSet, out ts))
{
if (OffSet == Index)//如果直接获取一个能用的,那就新建区为新区
{
Index++;
}
return ts;
}
return null;
}
}
/// <summary>
/// 是否阻塞增加
/// </summary>
/// <returns></returns>
public bool IsWaitAdd()
{
lock (Lock)
{
if (OffSet != Index)
{
return true;
}
return false;
}
}
/// <summary>
/// 当前队列完成
/// </summary>
public void Complete()
{
lock (Lock)
{
IList<T> ts;
taskQueues.TryRemove(OffSet, out ts);
if (OffSet < Index)
{
OffSet++;
}
}
}
public void Dispose()
{
if (taskQueues != null)
{
taskQueues.Clear();
taskQueues = null;
}
}
}
class Program
{
static TaskQueue<string> taskQueue;
static void Main(string[] args)
{
taskQueue = new TaskQueue<string>();
#region 一个一直生产指定大小,另外一个消费 先生产,再消费
//for (int i = 0; i < 1000; i++)
//{
// taskQueue.Add(i.ToString());
//}
另外一个按照指定的时间,消费
//while (true)
//{
// Thread.Sleep(2000);
// Console.WriteLine("获取-----开始获取到数据!");
// var list = taskQueue.GetQueue();
// if (list != null)
// {
// Console.WriteLine($"获取-----对象状态:{taskQueue.IsWaitAdd()}已获取的队列列表:{string.Join(",", list)}");
// Console.WriteLine("获取-----处理1秒后,提交当前!");
// Thread.Sleep(1000);
// taskQueue.Complete();
// Console.WriteLine("获取-----已经提交!");
// }
//}
#endregion
#region 两个任务处理,实现 一个生产,一个消费 批量 生产,并消费
Task.Run(() =>
{
for (int i = 0; i < 10000000; i++)
{
taskQueue.Add(i.ToString());
Thread.Sleep(100);//一秒插入一条
Console.WriteLine($"插入-----队列状态:{taskQueue.IsWaitAdd()}");
while (taskQueue.IsWaitAdd())//有待处理任务
{
Console.WriteLine("插入-----任务插入中开始阻塞!");
SpinWait.SpinUntil(() => !taskQueue.IsWaitAdd());
}
}
});
while (true)
{
Thread.Sleep(2000);
Console.WriteLine("获取-----开始获取到数据!");
var list = taskQueue.GetQueue();
if (list != null)
{
Console.WriteLine($"获取-----对象状态:{taskQueue.IsWaitAdd()}已获取的队列列表:{string.Join(",", list)}");
Console.WriteLine("获取-----处理10秒后,提交当前!");
Thread.Sleep(1000);
taskQueue.Complete();
Console.WriteLine("获取-----已经提交!");
}
}
#endregion
Console.WriteLine("开始获取信息!");
Console.ReadLine();
}
}
C# List分页处理
/// <summary>
/// List分页处理
/// </summary>
public class ListPage<T>
{
/// <summary>
/// 页数
/// </summary>
public int PageCount { get; set; }
/// <summary>
/// 当前页码
/// </summary>
public int CurrPage { get; set; }
/// <summary>
/// 一页多少条
/// </summary>
public int PageSize { get; set; }
/// <summary>
/// 数据源信息
/// </summary>
private List<T> DataSource { get; set; }
/// <summary>
/// 获取数据源和一页多少
/// </summary>
/// <param name="List"></param>
/// <param name="PageSize"></param>
public ListPage(List<T> List, int PageSize = 4, int CurrPage = 0)
{
DataSource = List;
this.PageSize = PageSize;
this.PageCount = (int)Math.Ceiling((decimal)DataSource.Count / PageSize);
this.CurrPage = CurrPage;
}
//是否有下一页
public bool HasNextPage
{
get { return CurrPage < this.PageCount; }
}
/// <summary>
/// 直接获取下一页
/// </summary>
/// <returns></returns>
public List<T> NextPage()
{
var data = DataSource.Skip((CurrPage) * PageSize).Take(PageSize).ToList();
CurrPage++;
return data;
}
/// <summary>
/// 获取指定页
/// </summary>
/// <returns></returns>
public List<T> getPage(int CurrPage)
{
var data = DataSource.Skip((CurrPage) * PageSize).Take(PageSize).ToList();
return data;
}
}
List<int> list = new List<int>();
list.Add(10);
list.Add(20);
list.Add(30);
list.Add(40);
list.Add(50);
list.Add(60);
list.Add(70);
list.Add(80);
ListPage<int> ts = new ListPage<int>(list,3);
while (ts.HasNextPage)
{
var obj = ts.NextPage();
foreach (var item in obj)
{
Console.WriteLine(item);
}
Console.WriteLine("输出完一页信息!");
}
var bb = ts.NextPage();
Console.WriteLine("123");
Console.ReadLine();
实用的配置文件类 方便统一使用 ConfigInfo
在敲代码过程中,经常会,左边写一个某某配置类,右边一个某某配置类,然后,对它进行抽象统一,写了一个,感觉比较好用。
/// <summary>
/// 配置信息(用来读取相应配置文件)
/// </summary>
public class ConfigInfo<T> where T : class, new()
{
/// <summary>
/// 配置地址
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 文件名
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 当前配置
/// </summary>
public T CurrentConfig { get; set; }
/// <summary>
/// 读写锁
/// </summary>
private ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
/// <summary>
/// 构造函数
/// </summary>
public ConfigInfo(string FileName)
{
this.FileName = FileName;
this.FilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileName);
CurrentConfig = Read();
}
/// <summary>
/// 读取配置信息
/// </summary>
/// <returns></returns>
public T Read()
{
T t = new T();
if (File.Exists(FilePath))
{
try
{
rwl.EnterReadLock();
var Str = File.ReadAllText(FilePath);
if (!string.IsNullOrEmpty(Str))
{
try
{
t = JsonConvert.DeserializeObject<T>(Str);
CurrentConfig = t;
return t;
}
catch (Exception)
{ }
}
}
finally
{
rwl.ExitReadLock();
}
}
else
{
Save(t);
}
return t;
}
/// <summary>
/// 写配置
/// </summary>
/// <param name="t"></param>
public void Save(T t)
{
try
{
rwl.EnterWriteLock();
if (!File.Exists(FilePath))
{
try
{
Directory.CreateDirectory(new FileInfo(FilePath).DirectoryName);
CurrentConfig = t;
}
catch (Exception)
{ }
}
File.WriteAllText(FilePath, JsonConvert.SerializeObject(t));
}
catch (Exception)
{
}
finally
{
rwl.ExitWriteLock();
}
}
/// <summary>
/// 写配置
/// </summary>
/// <param name="t"></param>
public void Save()
{
try
{
rwl.EnterWriteLock();
if (!File.Exists(FilePath))
{
try
{
Directory.CreateDirectory(new FileInfo(FilePath).DirectoryName);
}
catch (Exception)
{ }
}
File.WriteAllText(FilePath, JsonConvert.SerializeObject(CurrentConfig));
}
catch (Exception)
{
}
finally
{
rwl.ExitWriteLock();
}
}
}
一个简单的客户端配置类
/// <summary>
/// 客户端配置
/// </summary>
public class ClientConfig
{
/// <summary>
/// 服务地址
/// </summary>
public string Server { get; set; }
}
具体的用法:
ConfigInfo<ClientConfig> configInfo = new ConfigInfo<ClientConfig>("ClientConfig.cfg");
configInfo.CurrentConfig.Server = "10";
configInfo.Save();
configInfo.Read();
configInfo.CurrentConfig.Server = "100";
configInfo.Save();
从结果来看,使用还是很方便的,以后类也方便管理了
引用地址
https://blog.csdn.net/i2blue/article/details/103663335
https://blog.csdn.net/i2blue/article/details/93723123
https://blog.csdn.net/i2blue/article/details/105020879