public void DoubleStopTest() { //arrange var producer = new ProducerConsumer <Block>(); var block = new Block(0, null); //act producer.Stop(); producer.Stop(); //assert Assert.ThrowsException <InvalidOperationException>(() => producer.Enqueue(block)); }
public void DequeueTest_DequeueItemFromStoppedQueueIsNull() { //arrange var producer = new ProducerConsumer <Block>(); //act producer.Stop(); var resultItemFromDequeue = producer.Dequeue(); //assert Assert.IsNull(resultItemFromDequeue); }
public int Run() { try { workingThreads.ForEach(thread => thread.Start()); while (!interrupted) { if (tasks.Size() > 2 * concurrency || results.Size() > 2 * concurrency) { Thread.Yield(); continue; } var data = getDataBlock(); if (data == null) { tasks.Stop(); break; } tasks.Enqueue(data); } // join only processing tread and not the result aggregator for (var i = 1; i < workingThreads.Count; i++) { workingThreads[i].Join(); } // notifies the result aggregator thread that no new information would be added and wait for it to finish results.Stop(); workingThreads[0].Join(); } catch (HandledException e) { this.Interrupt(); } catch (Exception e) { Console.WriteLine($"Unhandled exception: {e.Message}"); this.Interrupt(); } return(interrupted ? 1 : 0); }
// This is a HUGE test which involves actual threads and takes time, // so technically it is not a unit test. // But this is a sort of pet-form of the whole project, and covers the main sense of it. // Actually, this is a code of my prototype application so it is also not well structured. // // Whats going on: // - "Reader" thread produces a sequence of numbers and passes to Producer-Consumer (P-C) // - A number of worker threads consume and "process" them (actually do nothing with a random delay) // then pass to the next P-C // - A "writer" thread collects all the integers passed in the list. // The goal of the test is to ensure that the final list contains exactly the same numbers // as produced by "reader" public void ProducerConsumerShouldWork() { var readerPc = new ProducerConsumer <IntTask>(8, new ProducerConsumerQueue <IntTask>()); var processorsPcs = new List <ProducerConsumer <IntTask> >(); var finishPc = new ProducerConsumer <IntTask>(8, new ProducerConsumerQueue <IntTask>()); const int integersToReadCount = 50; var integersToRead = new List <int>(integersToReadCount); var rand = new Random(DateTime.Now.Millisecond); for (var i = 0; i < integersToReadCount; i++) { integersToRead.Add(rand.Next(10000)); } var readerThread = new Thread(new ThreadStart(() => { var rnd = new Random(DateTime.Now.Millisecond); var currId = 0; for (int i = 0; i < integersToReadCount; i++) { var pc = new IntTask { Id = i, Data = integersToRead[i] }; readerPc.Push(pc); Thread.Sleep(rnd.Next(10)); currId++; } readerPc.Stop(); var endPc = new IntTask { Id = currId, Data = 0 }; finishPc.Push(endPc); })); readerThread.Start(); for (int i = 0; i < 4; i++) { var processorId = i; var prodCons = new ProducerConsumer <IntTask>(4, new ProducerConsumerOrderedQueue <IntTask>()); processorsPcs.Add(prodCons); var processorThread = new Thread(new ThreadStart(() => { var rnd = new Random(DateTime.Now.Millisecond); var pc = readerPc.Pop(); while (pc != null) { processorsPcs[processorId].Push(pc); pc = readerPc.Pop(); Thread.Sleep(rnd.Next(1000)); } })); processorThread.Start(); } var writerList = new List <int>(integersToReadCount); var writer = new Thread(new ThreadStart(() => { int currId = 0; while (true) { var allProcessorsEmpty = true; for (int i = 0; i < processorsPcs.Count; i++) { var t = processorsPcs[i].Peek(); if (t != null) { allProcessorsEmpty = false; if (t.Id == currId) { t = processorsPcs[i].Pop(); writerList.Add(t.Data); currId++; } } } if (allProcessorsEmpty) { var finishPcData = finishPc.Peek(); if (finishPcData != null && finishPcData.Id == currId) { break; } } } })); writer.Start(); writer.Join(); Assert.IsTrue(integersToRead.SequenceEqual(writerList)); }
private void btn_Satrt_Click(object sender, EventArgs e) { if (!_noticeFlag) { _noticeFlag = true; _noticeDateTime = DateTime.Now; Logging("启动[提醒]服务"); SetbtnState(btn_Satrt, "停止[提醒]服务", true); SetlblState(lbl_State, "[提醒]扫描服务运行中(" + _noticeDateTime + ")", Color.Green); //重置提醒扫描状态:正在扫描--> 等到扫描 var resetStandbyTask = new Task <bool>(() => { var isReset = false; try { isReset = ResetAllRemindScan(); } catch { } return(isReset); }); resetStandbyTask.Start(); resetStandbyTask.Wait(); var isSuccess = resetStandbyTask.Result; if (isSuccess) { Logging("重置\"扫描中\"的[提醒]扫描服务为等待扫描成功!"); } else { Logging("[提醒]扫描服务启动失败:重置\"扫描中\"的[提醒]扫描服务为等待扫描失败!"); _noticeFlag = false; SetbtnState(btn_Satrt, "启动[提醒]扫描服务", true); SetlblState(lbl_State, "[提醒]扫描服务停止", Color.Red); return; } //初始化相关变量、工作线程 //等到重置“发送中”任务结束后,才能执行下面任务: //获取[未提醒]列表数据,为[发起提醒]生产者提供生产方法 var getRetryTimes = 0; Func <List <string> > ProduceFunc = () => { //休眠获取[提醒]列表数据,主要为了间断查询。 Thread.Sleep(_SleepQuery); var unList = new List <string>(); try { unList = GetTaskList(); if (unList.Count > 0) { Logging("获取[提醒]队列成功!"); } getRetryTimes = 0; } catch (Exception ex) { getRetryTimes = getRetryTimes + 1; if (getRetryTimes >= _GetQueryRetryTimes) { _noticeFlag = false; Logging( "[提醒]服务意外停止:获取[未提醒]队列连续失败" + getRetryTimes + "次!|| 错误原因:" + (ex.InnerException == null ? ex.Message : ex.InnerException.ToString()), (string.IsNullOrWhiteSpace(ex.StackTrace) ? "" : ex.StackTrace)); ChangeAllServerState(); if (_producerConsumer != null) { _producerConsumer.Stop(); } } else { Logging( "获取[未提醒]队列连续失败" + getRetryTimes + "次!|| 错误原因:" + (ex.InnerException == null ? ex.Message : ex.InnerException.ToString()), (string.IsNullOrWhiteSpace(ex.StackTrace) ? "" : ex.StackTrace)); } } return(unList); }; int consumeRetryTimes = 0; //为[未提醒]消费者提供消费方法 Action <string> notNoticeAction = item => { if (!string.IsNullOrEmpty(item)) { long durTime = -1; var durTimeUnit = "毫秒"; var durTimer = new Stopwatch(); durTimer.Start(); try { //执行活动提交服务 var result = PostRemind(item); durTimer.Stop(); durTime = durTimer.ElapsedMilliseconds; if (durTime >= 1000) { durTimeUnit = "秒"; durTime = durTime / 1000; } lock (_noticeLock) { consumeRetryTimes = 0; } Logging("[未提醒]提交成功." + "(商家ID:" + item + ",运行结果:" + (result ? "提醒成功" : "提醒失败") + ",耗时:" + durTime.ToString() + durTimeUnit + ")"); } catch (Exception ex) { lock (_noticeLock) { consumeRetryTimes++; if (consumeRetryTimes >= _GetQueryRetryTimes) { _noticeFlag = false; Logging( "[未提醒]服务意外停止:提交提醒服务连续失败" + consumeRetryTimes + "次![其中包含ID:" + item + "] || 错误原因:" + (ex.InnerException == null ? ex.Message : ex.InnerException.ToString()), (string.IsNullOrWhiteSpace(ex.StackTrace) ? "" : ex.StackTrace)); ChangeAllServerState(); if (_producerConsumer != null) { _producerConsumer.Stop(); } } else { Logging( "[未提醒]提交提醒服务连续失败" + consumeRetryTimes + "次![其中包含商家ID:" + item + "] || 错误原因:" + (ex.InnerException == null ? ex.Message : ex.InnerException.ToString()), (string.IsNullOrWhiteSpace(ex.StackTrace) ? "" : ex.StackTrace)); } } } Thread.Sleep(_SleepPost); } }; //构造生产消费模式,初始化如生产方法,消费方法,指定消费者数量 _producerConsumer = new ProducerConsumer <string>(ProduceFunc, notNoticeAction, _remainStandbyCount, _reminTaskNum); _producerConsumer.Start(); } else //停止 { _noticeFlag = false; if (_producerConsumer != null) { _producerConsumer.Stop(); } Logging("手动停止[未提醒]扫描服务"); SetbtnState(btn_Satrt, "启动[提醒]扫描服务", true); SetlblState(lbl_State, "[提醒]扫描服务停止", Color.Red); } }