初始化不统一控制好,引发的血案
问题描述
多线程下载:简单多个任务下载无问题,大批量下载任务,出现部分任务丢失问题
问题现象
- 问题 1:添加完任务后,update 不自动执行,需要通过直接调用 Update 才执行(没有深究其原因,就先临时这么处理了,于是就引发后面的诡异问题)
- 问题 2:简单多个任务下载无问题,大批量下载任务,出现部分任务丢失问题
思考问题 2
既然不大量下载就没有问题,那就弄个最简单的批量下载来复现问题,接下来就发现了以下新问题 3
- 问题 3:共享队列刚刚添加完 item,update 的时候队列总是为空
思考问题 3
- 思考 1:多线程导致数据不一致问题,添加在一个线程,update 在另外一个线程(已添加了锁,不应该是这个问题)
- 思考 2:哪里把数据又删除了 或者把队列重置了(仔细检查了一遍删除相关代码无问题,把所有队列赋值的地方加个断点调试一下,发现只有 1 处地方,运行发现执行了 2 次,原因:CDLWork 对象 init 两次导致)
回顾一下代码
场景代码
CDLWork
csharppublic class CDLWork : Singleton<CDLWork>, IInit, IDispose { private Queue<SDLTaskItem> m_waitItems; private readonly object m_object = new object(); public void Init() { m_waitItems = new KPriorityQueue<int, SDLTaskItem, int>(); } public void AddTask(SDLTaskItem taskItem) { //1.添加任务 lock (m_object) { m_waitItems.Enqueue(taskItem); } //添加完任务后,外层update执行刷新不到任务,需要通过直接调用Update才正常 Update(); } //2.外层调用Update刷新任务 public void Update() { __OnUpdate(); } private void __OnUpdate() { lock (m_object) { __AutoAddToExcuteList(); __StartMultiTask(); } } private void __StartMultiTask() { //3.问题:在此发现m_waitItems为空 if (m_excuteItems.Count <= 0) { return; } } }
具体原因
CMApplication
csharppublic class CMApplication : Singleton<CMApplication>, IInit, IDispose { public void Init() { ... m_dlWork = new CDLWork(); m_dlWork.Init(); if (null == m_mainThread) { m_bFlag = true; m_mainThread = new Thread(__Run); m_mainThread.Start(); } } private void __Run() { while (m_bFlag) { ... m_dlWork.Update(); ... Thread.Sleep(N_MAIN_THREAD_DELAY); } } }
Program
csharpstatic class Program { static void Main() { Init(); } static void Init() { //1.系统初始化 CMApplication.Instance.Init(); //2.Case初始化 CDLWork.Instance.Init(); } }
使用的地方
csharpCDLWork.Instance.AddTask(task);
这样就明显的看出问题了,外层添加任务使用一个 CDLWork 单例对象,循环调用 CDLWork 的 Update 又是另外一个实例对象,这也就可以解释为啥 update 刷新不到任务了。
总结
- 自己明显的发现问题,采用回避的方式处理(偷懒),问题终究最后会暴露出来,而导致耗费更多的时间(提醒:以后千万不要用这种态度处理问题,别学我)