如上一篇专栏博文所描述,Worklist可以看做是PACS系统、MODALITY设备和RIS系统之间的信息交换。从RIS系统到MODALITY通过Worklist可以提供诸如患者个人信息(姓名、年龄、生日等)和其他管理数据,以及提供关于成像过程和产生图像相关的一个唯一UID等信息。基本的结构如下图:
上一次利用DCMTK开源库顺利的模拟了“发送C-Find请求,查询worklist信息”的整个过程,通过利用DCMTK开源库提供的wlmscpfs.exe和findscu.exe工具包,使得模拟过程简单明了。此次希望通过fo-dicom(C#版的DCMTK)库来模拟该过程。
为了使得该模拟过程与上一篇博文的过程具有可比性,此次只利用fo-dicom库来构建C#版本的发送C-Find请求的过程,worklist服务端依然使用DCMTK提供的工具包wlmscpfs.exe。
具体代码如下,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dicom;
using Dicom.Network;
using Dicom.Log;
namespace FindSCU1
{
class Program
{
static void Main(string[] args)
{
string id = "123456";
var cfind = DicomCFindRequest.CreateWorklistQuery(patientId: id);
cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) =>
{
Console.WriteLine("********Patient Name is {0}**********", rp.Dataset.Get(DicomTag.PatientName));
};
var client = new DicomClient();
client.AddRequest(cfind);
client.Send("127.0.0.1", 104, false, "SCU-LargeV", "OFFIS");
Console.Read();
}
}
}
利用wlmscpfs.exe开启worklist服务,输入如下指令:
>wlmscpfs.exe 104 –d –dfp d:\DcmWorklist\wlistdb
显示效果如下:
表示worklist服务端已经顺利启动……
找到步骤2)中生成的可执行程序FindSCU1.exe,双击直接运行,此时服务端和客户端的结果如下:
只是简单的发送了一次以PatientID为目标的worklist查询服务,代码总共没有几行的,为什么会出现异常呢?根据上述客户端的异常提示,通过单步调试,定位到首次抛出异常的“事故点”:DicomDatasetReaderObserver.cs的OnElement函数中,该函数是从DicomReader.cs的ParseDataset函数中跳转过来的。截取OnElement函数的代码,
发现该函数内部,由于无法识别VR类型为SQ的字段,因此而抛出了throw new DicomDataException("Unhandled VR in DICOM parser observer: {0}", vr.Code)异常。
仔细回想一下我们的代码在哪个位置会出现SQ类型的字段呢?只有在CreateWorklistQuery函数中可能添加过SQ类型的字段,进入到DicomCFindRequest.cs中的CreateWorklistQuery函数内部,发现的确有如下代码:
dimse.Dataset.Add(new DicomSequence(DicomTag.ReferencedStudySequence));
为了证实我们的猜测,此处直接将该行代码注释掉,然后在fo-dicom源码工程中编译DICOM工程,重新生成Dicom.dll程序集。重新编译运行我们的测试工程FinSCU1.exe。服务端和客户端能够顺利运行,
修改fo-dicom库源码毕竟不是常规方法,在网络上搜索发现Github上有人遇到过类似的情形(https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073,如下图)最终也是修改fo-dicom源代码解决的。所以猜测可能是fo-dicom源代码中的部分逻辑还没有完善,还存在着些许漏洞。
为了验证是否是由于dimse.Dataset.Add(new DicomSequence(DicomTag.ReferencedStudySequence));添加了SQ格式的字段而导致的服务端错误,我们利用上次创建wlistqry.wl查询文件的DCMTK工程,向其中写入SQ格式的(0008,1110)DCM_ReferencedStudySequence字段,代码如下:
dataset->insertEmptyElement(DCM_ReferencedStudySequence);
然后利用findscu.exe 来进行查询操作,查看worklist服务端程序wlmscpfs是否正常,验证结果图如下:
由此证明,根本原因并不是由于WorklistQuery中插入了SQ格式的字段所引起的,在此仅仅标记一下,等待后续的继续排查和验证。
(未完待续……)
时间:2014-09-01