在C#内部使用TPL内部服务的基本设计模式
我正在尝试构建Windows服务,它需要某种并行性来汇集来自不同ftp源的文件。 为了启动多个ftp下载,我正在寻找TPL库来轻松地进行foreach循环并使并行性变得非常容易。 但是当我搜索如何启动或停止我的服务时,我最好的资金是在OnStart()
方法中创建新线程,如下所述https://stackoverflow.com/a/4865893/69433
阅读有关TPL的信息,请注意TPL比手动线程和手动停止线程更先进。
我没有找到任何描述如何在WindowsService中进行TPL循环的示例post?
我的代码:
protected override void OnStart(string[] args) { _thread = new Thread(WorkerThreadFunc); _thread.Name = "My Worker Thread"; _thread.IsBackground = true; _thread.Start(); }
而在WorkerThreadFunc
里面做了那种TPL
private void WorkerThreadFunc() { foreach (string path in paths) { string pathCopy = path; var task = Task.Factory.StartNew(() => { Boolean taskResult = ProcessPicture(pathCopy); return taskResult; }); task.ContinueWith(t => result &= t.Result); tasks.Add(task); } }
或者我应该开始我的WorkerThreadFunc作为任务?
这里需要注意的不仅仅是你如何开始你的工人,还有你如何实际阻止它。
除了Task本身,TPL还通过使用CancellationToken
和CancellationTokenSource
对象为您提供了一种非常方便的任务取消方式。
使用TPL启动和停止Windows服务
要将此技术应用于Windows服务,您基本上需要执行以下操作:
private CancellationTokenSource tokenSource; private Task backgroundTask; protected override void OnStart(string[] args) { tokenSource = new CancellationTokenSource(); var cancellation = tokenSource.Token; backgroundTask = Task.Factory.StartNew(() => WorkerThreadFunc(cancellation), cancellation, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
笔记:
在OnStop方法中,您触发取消并等待任务完成:
protected override void OnStop() { bool finishedSuccessfully = false; try { tokenSource.Cancel(); var timeout = TimeSpan.FromSeconds(3); finishedSuccessfully = backgroundTask.Wait(timeout); } finally { if (finishedSuccessfully == false) { // Task didn't complete during reasonable amount of time // Fix your cancellation handling in WorkerThreadFunc or ProcessPicture } } }
消除
通过调用tokenSource.Cancel();
我们只是告诉这个tokenSource
发出的每个CancellationToken
被取消,并且接受这种令牌的每个方法(比如你的WorkerThreadFunc)现在应该停止它的工作。
处理取消特定于实现,但一般规则是您的方法应该监视取消令牌状态并能够在合理的时间内停止其工作 。 这种方法要求您在逻辑上将您的工作分成更小的部分,这样您就不会停留在需要大量时间完成的工作上,如果请求取消则不会启动任何新工作。
查看您的WorkerThreadFunc代码,您可以考虑在执行每个新的ProcessPicture
任务之前检查取消,例如:
private List tasks = new List (); private void WorkerThreadFunc(CancellationToken token) { foreach (string path in paths) { if (token.IsCancellationRequested) { // you may also want to pass a timeout value here to handle 'stuck' processing Task.WaitAll(tasks.ToArray()); // no more new tasks break; } string pathCopy = path; var task = Task.Factory.StartNew(() => { Boolean taskResult = ProcessPicture(pathCopy, token); // <-- consider a cancellation here return taskResult; }, token); // <<--- using overload with cancellation token task.ContinueWith(t => result &= t.Result); tasks.Add(task); } }
如果ProcessPicture
需要很长时间才能完成,您可能还需要在其中添加取消支持。 与WorkerThreadFunc类似,您应该考虑ProcessPicture
实现。 这里的关键想法是找到一个可以安全地停止工作并从方法返回的地方。 安全地我的意思是 – 不要让系统或数据处于破碎状态。
除了在WorkerThreadFunc中监视IsCancellationRequested
之外,您还可以Register
将在请求取消时执行的回调,以执行其他一些操作,例如清理等:
token.Register(CancellationCallback);
和
上述就是C#学习教程:在C#内部使用TPL内部服务的基本设计模式分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
private void CancellationCallback() { // wait for all tasks to finish // cleanup }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/943052.html