大循环改造
有时候会看到在代码中存在一个大循环,整个过程需要执行很久,例如:
// 获取所有租户ID清单
List<string> list = GetAllTenantId();
// 用StringBuilder来存储所有租房的处理过程
StringBuilder sb = new ();
foreach(string tenantId in list) {
// 在循环中一次处理一个租户
string text = ProcessTenant(tenantId);
sb.AppendLine(text);
}
// 给外界发送通知
SendNotify(sb.ToString());
推荐的实现方式
1,先定义消息类型
public class WorkArgs {
public string TenantId {get; set;}
public string 其它所需的参数 {get; set;}
// 用于记录执行过程中产生的消息(此属性不是必需)
public StringBuilder Messages;
// 用于记录执行了多少次(此属性不是必需)
public ValueCounter ExecCounter;
}
2,程序初始化时注册消息订阅者
private static readonly MemoryMesssageQueue<Product> s_syncMMQ
= new MemoryMesssageQueue<Product>(MmqWorkMode.Sync);
MmqSubscriber.Start<WorkArgs, DemoMssageHandler>(new MmqSubscriberArgs {
Queue = s_syncMMQ,
SubscriberCount = LocalSettings.GetUInt("DemoMssageHandler_Subscriber_Count", 5)
});
3,用BackgroudTask来产生子任务消息
public class Task1 : BackgroundTask
{
public override int? SleepSeconds => 3600; // 假设1小时执行一次
public override void Execute()
{
// 获取所有租户ID清单
List<string> list = GetAllTenantId();
// 用StringBuilder来存储所有租房的处理过程
StringBuilder sb = new ();
ValueCounter counter = new ();
counter.Set(list.Count);
foreach(string tenantId in list) {
WorkArgs args = new WorkArgs{
TenantId = tenantId,
Messages = sb,
ExecCounter = counter
};
s_syncMMQ.Write(args);
}
}
}
4,执行子任务逻辑-MessageHandler
public class DemoMssageHandler : BaseMessageHandler<WorkArgs>
{
public override void ProcessMessage(PipelineContext<WorkArgs> context)
{
// 获取消息对象
WorkArgs args = context.MessageData;
string text = ProcessTenant(args);
lock(args.Messages){
args.Messages.AppendLine(text);
}
long count = args.ExecCounter.Decrement();
if( count == 0 ){ // 所有子任务已全部执行结束
SendNotify(sb.ToString());
}
}
}