public CreateScriptTaskResult CreateScriptTask(ScriptBase script) { var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var task = new Task(() => { var viewportRect = mumuTools.GetMumuViewportRect(); var viewportCapture = tools.DoCaptureScreen(viewportRect); logTools.Info("ScriptStart", $"Script: {script.Name} OnStart"); script.OnStart(viewportCapture.ToOpenCvMat(), viewportRect); while (true) { if (token.IsCancellationRequested) { logTools.Info("ScriptLoop", Trans.T("脚本: {0} 被终止", script.Name)); break; } try { Thread.Sleep(script.Interval); viewportRect = mumuTools.GetMumuViewportRect(); viewportCapture = tools.DoCaptureScreen(viewportRect); //logTools.Info("ScriptLoop", $"Script: {script.Name} Tick"); var viewportMat = viewportCapture.ToOpenCvMat(); var startTime = DateTime.Now; script.Tick(viewportMat, viewportRect); var endTime = DateTime.Now; //logTools.Info("ScriptLoop", $"Tick Takes {(endTime - startTime).TotalMilliseconds}ms"); } catch (Exception e) { var needBreak = logTools.IsSelfOrChildrenBreakException(e); if (!script.CanKeepOnWhenException || needBreak) { logTools.Error("ScriptLoop", Trans.T("脚本: {0} 因发生错误或主动结束而被终止", script.Name), false); throw e; } else { logTools.Error("ScriptLoop", Trans.T("脚本: {0} 发生错误", script.Name), false); logTools.Error("ScriptLoop", e); } } } }, tokenSource.Token); task.ContinueWith((t) => { if (t.IsFaulted) { logTools.Error("ScriptTask", t.Exception); } else if (t.IsCanceled) { logTools.Error("ScriptTask", Trans.T("脚本: {0} 被终止", script.Name)); } OnScriptEnded?.Invoke(script); }); return(new CreateScriptTaskResult() { Task = task, Script = script, TaskTokenSource = tokenSource, TaskToken = token, }); }