日积(Running)月累(ZSSURE):Task之CancelOpenAccess之Delete及fo-dicom之DeepCopy
Posted zssure
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日积(Running)月累(ZSSURE):Task之CancelOpenAccess之Delete及fo-dicom之DeepCopy相关的知识,希望对你有一定的参考价值。
题记:
近期看了一篇关于架构方面的良心长文你的架构是如何一步步腐化的?,文中字字句句道出了诸多从业者、初创企业,以及BAT都会遇到的问题,细细品读后觉得工作生活中的诸多情况皆如此,都会有一个体量由小到大的增长过程,这就面临着如何管理的问题,逐步优化 or 推倒重来?
背景:
博客中的【日积(Running)月累(ZSSURE)】系列,用于记录平日里学习和工作中遇到的问题,然并不意味着每个问题都是多大的“坑”。作为程序员应该都有过这样的体会,“调试了一整天程序,结果发现是某个变量名称写错了,亦或是其他种种低级而low的错误……”。所谓的成长有其广度的一面,那就是你要随时准备接受新技术、新技能;同时也有其深度的一面,那就是静静思考。很多看似简单的问题,求根溯源找到解决方案就是一种常见的思考方式,是锤炼深度的必由之路。
对于初入职场的新人,往往会因为接触了新的技能、熟悉了新的领域而兴奋不已,总希望能够学习新的东西,能够追随大牛or大神的脚步。随着时间的流逝兴趣、热情逐渐消散,到头来却是“竹篮子打水”,一无所获。
今年日常事务繁多,发现写博的量有所下降,自己虽不追求量,但细细回想2015,似乎没有多少的收获,这从一个侧面说明了在熙熙攘攘、纷繁吵杂的工作和生活中留给自己静静思考的时间少了,对知识、技能深度的把握少了。作家格拉德威尔在《异类》一书中指出:“人们眼中的天才之所以卓越非凡,并非天资超人一等,而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。”这也就是“一万小时定律”。
细想一下,设:
每篇博文成文前思考整理时间是4(单位:小时),编写发布时间是2。那么,一万小时=10000/6=1667(篇)。按照平均每月4篇,需要34年(417个月)。还是蛮恐怖的一件事情,不是么?
问题&解决方案:
【问题1】 .NET中Task任务的取消
【问题描述】:近日在监控基于WCF的DICOM服务模块时发现控制台总会莫名的多出一些线程(其实是Task)占用系统资源,导致每隔一段时间需要重启服务才能彻底释放。
【问题根源】:通过调试跟踪,发现在响应不同用户需求时会出现中断之前需求的情况,然而此种情况下由被中断的操作所创建的Task任务却依然在运行。
【解决方案】在Task任务内部使用CancellationTokenSource监控当前操作是否已被中断。
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
public CancellationTokenSource CannelToken
get return _cts;
private void StartSubTaskUntilCancel()
Task.Factory.StartNew(new Action(() =>
while (true)
_cts.Token.ThrowIfCancellationRequested();
Thread.Sleep(500);
System.Console.WriteLine(DateTime.Now.ToLongTimeString());
));
关于Task任务的中断在WinForm界面开发中要额外注意,之前学习Task的使用方法时大多是在控制台下单独练习并未考虑到用户操作,以及WinForm中自身的消息循环机制。举例说明如下:
如上图所示,在主窗口“开启新窗体”按钮响应里,弹出子窗体TaskForm时启动了一个Task用于实时输出当前时间。按照之前传统的思路,在TaskForm窗体中创建的Task在关闭窗体后会自动退出(这就是由控制台环境下练习导致的惯性思维)。然而当我们关闭子窗体TaskForm时,会发现时间依然在输出。那么如何才能根据用户交互来是的Task适当退出呢?——就是上面提到的CancellationTokenSource。在子窗体的FormClosed事件响应中调用CancellationTokenSource的Cancel方法即可通知Task退出。在分析Task以及线程池时可以使用Process Explorer的.NET Performance
具体细节可参考博文8天玩转并行开发——第二天 Task的使用和C# CancellationTokenSource 终止线程。
【问题2】Telerik OpenAccess的记录删除
【问题描述】在使用Telerik OpenAccess来作为数据库操作中间件时,需要删除相关的记录,包括单条记录和多条记录。
【解决方案】直接使用OpenAccessContext的Delete方法即可。详情参考How to: Delete Objects
【问题3】fo-dicom的DcmDataset的DeepCopy和ShallowCopy
【问题描述】在使用fo-dicom作为自有数据格式与DICOM格式相互转换时,发现最终转换成的DICOM文件的部分字段相同,都等于最后一次转换时所赋的值。
【问题根源】这个问题应该是由于fo-dicom的C-STORE发送机制以及对象的浅拷贝造成的,关于fo-dicom的C-STORE的流程参见之前的博文DICOM:fo-dicom之C-STORE再分析‘解决System.ObjectDisposedException异常’,对于C-STORE服务通常是先将所有的数据统一添加到待发送队列中,然后调用send命令统一发送。由于每次转换数据时使用的DcmDataset是同一个对象,对于部分字段并没有逐个进行深度拷贝,因此会导致最终所有DICOM文件的部分字段一致。
【解决方案】使用DcmDataset的CopyTo函数即可解决。
DicomDataset tmpDataset = new DicomDataset();
dataset.CopyTo(tmpDataset);
关于.NET的DeepCopy与ShallowCopy可参考博文Shallow Copy And Deep Copy。
作者:zssure@163.com
时间:2016-01-16
以上是关于日积(Running)月累(ZSSURE):Task之CancelOpenAccess之Delete及fo-dicom之DeepCopy的主要内容,如果未能解决你的问题,请参考以下文章
日积(Running)月累(ZSSURE):看山不是山看水不是水,2017
日积(Running)月累(ZSSURE):nginx配置putty连接保持以及AngularJS作用域$scope
日积(Running)月累(ZSSURE):Task之CancelOpenAccess之Delete及fo-dicom之DeepCopy
日积月累Shader - 09 分形图 / Patterns图案