The MWLSCU example demonstrates how to use DCF to implement a modality worklist service class user.
Classes
Class | Description | |
---|---|---|
Program |
Basic worklist service class user example which should be run with MWLSCP.
| |
ProgramMWLQueryListener |
This class wraps the worklist SCU and handles receiving worklist query responses.
Various properties on the scu object allow setting timeouts for various conditions.
|
Remarks
Supported OS Platforms:
- Windows - .Net Framework 4.7.2 64-bit and 32-bit
- Windows - .Net Core 2.1 64-bit and 32-bit
- Linux - .Net Core 2.1 64-bit
Examples
MWLSCU Sample Code
public class Program { /// <summary> /// The main entry point for MWLSCU. /// </summary> [STAThread] public static void Main() { MWLQueryListener listener = new MWLQueryListener(); listener.ExecuteQuery(BuildQuery()); if (System.Diagnostics.Debugger.IsAttached) { Console.Write("Press any key to continue . . . "); Console.ReadKey(); } } /// <summary> /// Build the QRIdentifier for this query. /// </summary> /// <remarks> /// We take the simple approach in this example of specifying an ISO_IR 100 character set for the /// encoding of our query request, which is probably fine for 90% of the Western languages. By a strict /// reading of the spec, the character set should only be specified if we actually require it in our /// query. Note that the SCP is free to ignore and/or not support our character set. /// <para> /// If you need to encode additional and/or multi-byte character sets, you may use the EncodingUtils.AnalyzeEncodings /// method in the CharacterSets namespace. /// </para> /// </remarks> /// <returns>The QRIdentifier dataset.</returns> private static QRIdentifier BuildQuery() { QRIdentifier query = new QRIdentifier(); //Fields to query on. query.PatientsName = "*STEPHEN"; //Fields to return. query.PatientId = ""; query.PatientsSex = ""; query.Modality = ""; query.StudyDate = ""; // Specify that this request contains ISO_IR 100 encoded data query.DataSet.Insert(Tags.SpecificCharacterSet, EncodingUtils.GetCharacterSetName(CharacterSetID.ISO_IR_100)); return query; } /// <summary> /// This class wraps the worklist SCU and handles receiving worklist query responses. /// Various properties on the scu object allow setting timeouts for various conditions. /// </summary> public class MWLQueryListener : IQueryListener { private static readonly ILogger Logger = LogManager.GetCurrentClassLogger(); private readonly DCF.Dicom.Worklist.MWLSCU _scu; /// <summary> /// Constructor creates the MWLSCU, and configures timeouts. /// </summary> public MWLQueryListener() { AssociationInfo ainfo = new AssociationInfo(); ainfo.CallingTitle = "SCU"; ainfo.CalledTitle = "SCP"; ainfo.CalledPresentationAddress = "localhost:10104"; // Add the requested presentation context RequestedPresentationContext ctx = new RequestedPresentationContext( 1, Uids.ModalityWorklistInformationModelFIND, Uids.ELE, Uids.ILE); ainfo.AddRequestedPresentationContext(ctx); // Make the SCU here _scu = new DCF.Dicom.Worklist.MWLSCU(ainfo, new DicomSessionSettings() { IsDebugEnabled = true, DebugFlags = DF.User8 }); _scu.MaxReturnedResults = 100; //scu_.QueryTimeoutSeconds = configuration_.QueryTimeoutSeconds; _scu.QueryTimeoutSeconds = -1; // We only use the progress timer, not the absolute timer _scu.SendDimseTimeoutSeconds = 30; _scu.ReceiveDimseTimeoutSeconds = 30; _scu.ProgressTimeoutSeconds = 30; } /// <summary> /// Execute a c-find request using the dataset in the QRIdentifier. /// </summary> /// <param name="query">the query dataset</param> public void ExecuteQuery(QRIdentifier query) { try { Logger.DebugFormat(DF.User8, "Query Data set is: {0}{1}", Environment.NewLine, query.DataSet); _scu.RequestAssociation(); _scu.CFind(query.DataSet, this, true); _scu.ReleaseAssociation(); } catch (Exception ex) { Console.WriteLine("Error executing query: {0}{1}{1}Please verify the Query SCP is up and running.", ex, Environment.NewLine); } } #region QueryListener Members /// <summary> /// This method is called at the completion of the query. /// </summary> /// <param name="status">The DIMSE status of the final response.</param> public void QueryComplete(int status) { Logger.InfoFormat("Received queryComplete event status = {0}", status); switch (status) { default: { Console.WriteLine("Operation status({0})", status); break; } case QueryListenerStatus.QUERY_LISTENER_SUCCESS: { Console.WriteLine("Operation finished with no errors."); break; } case QueryListenerStatus.QUERY_LISTENER_CANCELED: { Console.WriteLine("Operation was Canceled successfully"); break; } case QueryListenerStatus.QUERY_LISTENER_WARNING: { Console.WriteLine("Warning: some or all subops failed for C-MOVE"); break; } case QueryListenerStatus.QUERY_LISTENER_ERROR: { Console.WriteLine("Failure."); break; } case QueryListenerStatus.QUERY_LISTENER_INTERNAL_ERROR: { Console.WriteLine("Internal Error. Association may still be connected. Aborting"); if (_scu.Connected) { _scu.AbortAssociation(); } break; } case QueryListenerStatus.QUERY_LISTENER_TIMEOUT: { Console.WriteLine("Operation timed out"); if (_scu.Connected) { _scu.AbortAssociation(); } break; } case QueryListenerStatus.QUERY_LISTENER_SUCCESS_MAX_RETURNED_RESULTS_REACHED: { Console.WriteLine("Success, Max Returned Results Reached"); if (_scu.Connected) { _scu.AbortAssociation(); } break; } case QueryListenerStatus.QUERY_LISTENER_DIMSE_RECEIVE_TIMEOUT: { Console.WriteLine("Operation DIMSE receive timed out"); if (_scu.Connected) { _scu.AbortAssociation(); } break; } } } /// <summary> /// This method is called for all incoming DIMSE response messages. /// </summary> /// <param name="rsp">The DIMSE response messages.</param> public void QueryEvent(DimseMessage rsp) { // This method is called for both pending and final responses, so filter out // the final response (it doesn't have a data dataset, only a command dataset). if (rsp.DataSetType != 0x101) Console.WriteLine("Received response:{0}{1}", Environment.NewLine, rsp.Data); } #endregion } }