少年!看你骨骼惊奇,是万中无一的练武奇才,我这儿有本武林秘籍,见与你有缘就送你了!
如来神掌
Windows I/O完成端口是一个我至今都说不好的话题,请宽容的接受我这不是科班出身的自学成才的野生程序员身份。以前在上海一公司做产品追溯的时候,我的老大拿出一本《Windows核心编程》经常向我吹嘘什么“ Windows I/O完成端口”编程模型的时候我是云里雾里。后来看了公司常用的一个叫“线程池”的类的源码,豁然有点醒悟了,不就是类似Queue这样的东西么?按先进先出顺序处理业务数据,这明明就不是线程池啊,误导人了。但是这个类确实挺好用的,公司它都使用了很多年了。不想独享特此分享出来。
public class CoreThreadPool : IDisposable { ////// 队列元素申明 /// [StructLayout(LayoutKind.Sequential)] private class PoolData { ////// 外部要求放入队列的数据 /// public object Data; ////// 需要执行的命令(Exit/Command(自定义)) /// public PoolCommand Command; public PoolData() { Command = PoolCommand.Exit; } public PoolData(object data) { Data = data; Command = PoolCommand.Command; } public PoolData(PoolCommand cmd) { Command = cmd; } } protected enum PoolCommand { Command, Exit } protected SafeFileHandle complatePort; ////// 线程池主线程 /// protected Thread thread; protected volatile bool isOpened; [method: CompilerGenerated] [CompilerGenerated] public event Action
第1001次实践体验过程
上次做的人脸考勤程序在处理多个人同时考勤时我就使用了刚刚的类。
private CoreThreadPool pool = new CoreThreadPool(); private CoreThreadPool poolExt = new CoreThreadPool(); ... pool.Exceute += Pool_Exceute; pool.Start(); poolExt.Exceute += PoolExt_Exceute; poolExt.Start()
private void Pool_Exceute(object obj) { var entity = obj as UserInfo; if (entity == null) return; try { #region TODO本地防止重复请求 using (DefaultDbContext db = new DefaultDbContext()) { var dbEntity = db.Attenducelog.Where(e => e.Emp_No == entity.EmpNo).First(); DateTime dt; if (dbEntity == null) { //第一次考勤 dbEntity = new Attenducelog_Entity(); dbEntity.Emp_No = entity.EmpNo; dt = DateTime.Now.AddDays(-1); dbEntity.Log_DateTime = dt; db.Attenducelog.Add(dbEntity); db.SaveChanges(); } else { //已经多次考勤 dt = dbEntity.Log_DateTime; } TimeSpan ts = DateTime.Now - dt; if (ts.TotalSeconds 61) { return; } else { //已经多次考勤,本次成功了才记录打卡时间 dbEntity = db.Attenducelog.Where(e => e.Emp_No == entity.EmpNo).First(); dbEntity.Log_DateTime = DateTime.Now; db.Attenducelog.Update(dbEntity); db.SaveChanges(); } } #endregion string url = $"{config.AppSettings.Settings["Platform"].Value}/business/attendancedetails/AddAttendanceDetails"; #region dto PlatAttendanceDto dto = new PlatAttendanceDto(); dto.KeyId = Guid.NewGuid().ToString(); dto.Status = 0; dto.AuditDate = DateTime.Now.ToString("yyyy-MM-dd"); dto.CreateBy = "AttendanceClient"; dto.AttendanceDatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); dto.FkStore = config.AppSettings.Settings["StoreID"].Value; dto.EmpName = entity.Name; dto.EmpNo = entity.EmpNo; dto.WorkShift = ""; dto.LocalDatetime = DateTime.Now; #endregion string jsonData = JsonConvert.SerializeObject(dto); string rs = Program.PostJsonData(url, jsonData); if (!string.IsNullOrEmpty(rs) && JObject.Parse(rs).Valueint>("code").Equals(200)) { JObject rs_Object = JObject.Parse(rs); string data = rs_Object["data"].ToString(); JObject log = JObject.Parse(data); string sound_TIPS = log.Valuestring>("remark").Split("&".ToCharArray()).LastOrDefault(); string tips = "[" + entity.Name + "] " + log.Valuestring>("remark").Split("&".ToCharArray()).LastOrDefault(); AppSpVoiceSpeak(sound_TIPS); MessageTip.ShowOk(tips, 3000); } } catch (Exception ex) { if (ex.Message.Contains("无法连接到远程服务器")) { Thread.Sleep(100); ViewFaceCore.Controls.MessageTip.ShowError("无法连接到远程服务器" + Environment.NewLine + "Unable to connect to remote server", 300); } } finally { Thread.Sleep(100); } }
////// 持续检测一次人脸,直到停止。 /// /// 取消标记 private async void StartDetector(CancellationToken token) { Listdouble> fpsList = new Listdouble>(); double fps = 0; Stopwatch stopwatchFPS = new Stopwatch(); Stopwatch stopwatch = new Stopwatch(); isDetecting = true; try { if (VideoPlayer == null) { return; } if (token == null) { return; } while (VideoPlayer.IsRunning && !token.IsCancellationRequested) { try { if (CheckBoxFPS.Checked) { stopwatch.Restart(); if (!stopwatchFPS.IsRunning) { stopwatchFPS.Start(); } } Bitmap bitmap = VideoPlayer.GetCurrentVideoFrame(); // 获取摄像头画面 if (bitmap == null) { await Task.Delay(10, token); FormHelper.SetPictureBoxImage(FacePictureBox, bitmap); 服务器托管网 continue; } if (!CheckBoxDetect.Checked) { await Task.Delay(1000 / 60, token); FormHelper.SetPictureBoxImage(FacePictureBox, bitmap); continue; } List faceInfos = new List(); using (FaceImage faceImage = bitmap.ToFaceImage()) { var infos = await faceFactory.Get().TrackAsync(faceImage); for (int i = 0; i ) { Models.FaceInfo faceInfo = new Models.FaceInfo { Pid = infos[i].Pid, Location = infos[i].Location }; if (CheckBoxFaceMask.Checked || CheckBoxFaceProperty.Checked) { Model.FaceInfo info = infos[i].ToFaceInfo(); if (CheckBoxFaceMask.Checked) { var maskStatus = await faceFactory.Get().PlotMaskAsync(faceImage, info); faceInfo.HasMask = maskStatus.Masked; } if (CheckBoxFaceProperty.Checked) { FaceRecognizer faceRecognizer = null; if (faceInfo.HasMask) { faceRecognizer = faceFactory.GetFaceRecognizerWithMask(); } else { faceRecognizer = faceFactory.Get(); } var points = await faceFactory.Get().MarkAsync(faceImage, info); float[] extractData = await faceRecognizer.ExtractAsync(faceImage, points); UserInfo userInfo = CacheManager.Instance.Get(faceRecognizer, extractData); if (userInfo != null) { faceInfo.Name = userInfo.Name; faceInfo.Age = userInfo.Age; switch (userInfo.Gender) { case GenderEnum.Male: faceInfo.Gender = Gender.Male; break; case GenderEnum.Female: faceInfo.Gender = Gender.Female; break; case GenderEnum.Unknown: faceInfo.Gender = Gender.Unknown; break; } pool.Post(userInfo); } else { faceInfo.Age = await faceFactory.Get().PredictAgeAsync(faceImage, points); faceInfo.Gender = await faceFactory.Get().PredictGenderAsync(faceImage, points); } } } faceInfos.Add(faceInfo); } } using (Graphics g = Graphics.FromImage(bitmap)) { #region 绘制当前时间 StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; g.DrawString($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", new Font("微软雅黑", 32), Brushes.White, new Rectangle(0, 0, Width - 32, 188), format); g.DrawString($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", new Font("微软雅黑", 32), Brushes.White, new Rectangle(2, 2, Width - 32, 188), format); #endregion // 如果有人脸,在 bitmap 上绘制出人脸的位置信息 if (faceInfos.Any()) { g.DrawRectangles(new Pen(Color.Red, 4), faceInfos.Select(p => p.Rectangle).ToArray()); if (CheckBoxDetect.Checked) { for (int i = 0; i ) { StringBuilder builder = new StringBuilder(); if (CheckBoxFaceProperty.Checked) { if (!string.IsNullOrEmpty(faceInfos[i].Name)) { builder.Append(faceInfos[i].Name); } } if (builder.Length > 0) { g.DrawString(builder.ToString(), new Font("微软雅黑", 32), Brushes.White, new PointF(faceInfos[i].Location.X + faceInfos[i].Location.Width + 24, faceInfos[i].Location.Y)); g.DrawString(builder.ToString(), new Font("微软雅黑", 32), Brushes.White, new PointF(faceInfos[i].Location.X + faceInfos[i].Location.Width + 24 + 2, faceInfos[i].Location.Y + 2)); } } } } if (CheckBoxFPS.Checked) { stopwatch.Stop(); if (numericUpDownFPSTime.Value > 0) { fpsList.Add(1000f / stopwatch.ElapsedMilliseconds); if (stopwatchFPS.ElapsedMilliseconds >= numericUpDownFPSTime.Value) { fps = fpsList.Average(); fpsList.Clear(); stopwatchFPS.Reset(); } } else { fps = 1000f / stopwatch.ElapsedMilliseconds; } g.DrawString($"{fps:#.#} FPS", new Font("微软雅黑", 24)服务器托管网, Brushes.Green, new Point(10, 10)); } } FormHelper.SetPictureBoxImage(FacePictureBox, bitmap); } catch (TaskCanceledException) { break; } catch { } } } catch (Exception ex) { Program.AppLogger.Error(ex); } finally { isDetecting = false; } }
其实触发数据就一句代码,看起来像这样:pool.Post(userInfo);
好了,高手请看笑话吃瓜,有需要的同学可亲自尝试。bye 了个 bye!
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net