Comparison of MoveImages MoveSync GetUsingMove and Move

The COM_version of DicomObjects provides 4 different mechanisms for initiating C-MOVE operations, and we are often asked about the differences and relative benefits. This page is therefore a summary of the differences.

Contents

Why is C-MOVE so difficult?

The C-MOVE protocol itself is described here

There are several features of C-MOVE itself which are mode difficult to handle than most other operations, many of which related to the network problems associated with the need for a reverse association back from the server to the client - these are detailed in the page C-MOVE_Problems. In addition however, there is a need for the client program to be able to receive the images on that reverse connection, and to do so in a way which does not cause a deadlock.

The deadlock problem

This problem would arise if a single threaded program were to issue a C-MOVE request and simply wait for the C-MOVE to complete. The SCP would receive the request and send images using C-STORE on the secondary association to the client, which would trigger an Imagereceived (or ImageReceivedAsync) event. However, an event cannot fire whilst an outgoing COM operation is in progress, so the event would be queued waiting for the C-MOVE to complete. Therefore:

  • The SCP would be waiting for a response to the secondary C-STORE operation (which could not happen until the C-MOVE returns)
  • The SCU would be waiting for the C-MOVE to complete (which could not happen until the C-STORE returns)
  • Result = deadlock

There is no single solution to this issue but the COM version of Dicomobjects provides 4 to choose from (it is all a lot simpler in the .NET_Version which is free-threaded, avoiding the deadlock.

DicomQuery.MoveImages

This is the simplest of the solutions, but also the least reliable.

  • The C-MOVE is fired on a background thread
  • There is no possibility of deadlock
  • It is asynchronous, so the program does not "freeze" whilst the operation is in progress
  • but no result is available to the calling program - no errors are reported

DicomQuery.MoveSync

This is also very simple, but due to the deadlock issue is only suitable when doing a genuine third party C-MOVE operation - i.e. the recipient of the images is not the program issuing the C-MOVE request.

  • The C-MOVE is fired on the main thread
  • Deadlock will occur if the recipient is the same program
  • It is synchronous, so the GUI will be "frozen" whilst the operation is in progress
  • When the operation completes, the result status is available to the calling program, and any errors are reported

DicomQuery.GetUsingMove

This is a more complex solution, using an internal thread for listening. As it is quite complex, it has its own page - GetUsingMove

  • The C-MOVE is fired on the main thread
  • There is no possibility of deadlock
  • It is synchronous, so the GUI will be "frozen" whilst the operation is in progress
  • When the operation completes, the result status is available to the calling program, and any errors are reported

DicomConnection.Move

This is very different to the other methods, and is a little more complex to use, being based on the DicomConnection object rather than DicomQuery, but it by far the best, and the only one recommended for production use in workstations etc. The major advantage is that it is asynchronous (avoiding deadlocks and a frozen GUI) but still provides feedback when it completes by using the ActionComplete event. A full description with example code is given on the DicomConnection.Move page.

  • The C-MOVE is fired on a background thread
  • There is no possibility of deadlock
  • It is asynchronous, so the program does not "freeze" whilst the operation is in progress
  • When the operation completes, the result status is available to the calling program, and any errors are reported

Summary Table

  Object used C-MOVE Thread Receive Thread Can Deadlock Blocks the GUI Result Available
MoveImages DicomQuery Background Main No No No
MoveSync DicomQuery Main Main Yes Yes Yes
GetUsingMove DicomQuery Main Background No Yes Yes
Move DicomConnection Background Main No No Yes