Comparison of MoveImages MoveSync GetUsingMove and Move
The DicomObjects.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.
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 |