[CE U12 C#] PrintAPI - slow performance of CreatePrintDefinitions

The MSTNPlatformNET help contains (some) documentation for the PrintAPI. The section regarding the IPrintManager interface contains example code. In this example the seemingly innocent line:
IPrintDefinition[] printDefinitions = printSet.CreatePrintDefinitions (new FileSpec ("My Design.dgn"), null);

 
 appears to perform some really heavy work under the hood. In our case, it’s in the magnitude of 15 seconds on our midrange workstations. The dgn-file used is mostly empty aside from the sheet-model and a couple of line elements.

We tried looking for alternative means of instantiating the IPrintDefinition/ICadPrintDefinition objects, but IPrintSet.CreatePrintDefinitions (plural) appears to be the only way to conceive one. IPrintSet.CreatePrintDefinition (singular) takes an IPrintDefinition as a parameter and as such cannot be used as a starting point.

We also tried providing an IPrintStyle object to IPrintSet.CreatePrintDefinitions as the documentation for CreatePrintDefinitions  states that the printStyle-parameter (null in the example provided in the IPrintManager documentation) is A print style that will guide the creation of the print definitions. But to no avail either.
Is there any way to circumvent this long wait time that we’ve missed?
Parents
  • Congratulations for asking the first significant question I can recall regarding the re-invented Printing API published for the first time in CONNECT Edition.

     

    Regarding CreatePrintDefinitions, yes that method launches a worker process in order to load the specified DGN file and collect state information.  This API does not disturb the active interactive MicroStation session.  It is the underlying API used by Print Organizer, which is predominately a C# application.

     

    What you want is "IPrintSet.UseWorkerMicroStation = false".  That property needs to be set immediately after calling IPrintManager.CreatePrintSet, before calling InitializeFromPrinter.

     

    /*------------------------------------------------------------------------------------**/

    /// <summary>If True, a MicroStation worker process is used.</summary>

    /// <remarks>Defaults to True when the print set is constructed.

    /// If no worker MicroStation is desired, this property must be set prior to

    /// initializing the print set.</remarks>

    /*------------------------------+------------------------------------------------------*/

    bool                            UseWorkerMicroStation

        {

        get;

        set;

        }

     

    Traditionally the native code API has been used for applications that mimic the single-Print dialog, and that API does not use a worker process.  But the .NET API may be used as well.

          
    .

    Answer Verified By: Anders Sorgenfri Askholm 

  • Congratulations for asking the first significant question I can recall regarding the re-invented Printing API published for the first time in CONNECT Edition.

    Why, thank you!

    What you want is "IPrintSet.UseWorkerMicroStation = false".  That property needs to be set immediately after calling IPrintManager.CreatePrintSet, before calling InitializeFromPrinter.

    This does the trick.

    Although I will challenge the statement that the API does not disturb the active interactive Microstation session. When UseWorkerMicrostation is set to false, the workload of starting the new Microstation process is done on the main thread, subsequently blocking the UI (for 15 seconds). This was the issue to begin with. I tried executing the code asynchronously, but this threw exceptions all around. Could you provide a code example where this isn't the case?

    Also, when UseWorkerMicrostation is set to false and the active session is used, Microstation switches to and renders each model before printing it. Is there a bool property lurking somewhere to do away with this behaviour as well? The resulting screen flickering can be quite unpleasant.

  • Yes, when UseWorerMicroStation=False, the API most certainly disturbs the active session.  The .NET API is designed to support Print Organizer which uses a worker process to load DGNs without affecting the interactive session.  Setting UseWorkerMicroStation=False changes that behavior, forcing the .NET API into a mode that isn't used in vanilla MicroStation.

    The native code API is used by the single-Print dialog and is better suited to mimic its capabilities.  "print" key-ins are also a good choice and is what most custom print automation tools use.  The print key-ins can be invoked from either .NET or native code applications, or VBA macros.

    With UseWorkerMicroStation=False, there is no background process started.  The time delay you refer to is probably loading the DGN you specified in CreatePrintDefinitions() into the interactive process session, replacing the previously active DGN.  (Assuming they are different; if you specify the currently-loaded DGN, it is not force re-loaded.)

    The extensive DGN processing performed during CreatePrintDefinitions and Preview/Plot must be done on the main thread.  It cannot be moved to a worker thread while allowing the MicroStation message loop / user interface to continue running on the main thread.  That's one reason Print Organizer uses a separate worker process, to allow the interactive process to continue refreshing its user interface while the background process does its work on its main thread.

    The best you can do when performing printing work within the interactive process is to display a "working" status dialog in a background thread while the main thread does its job.

    If you're looping through a set of DGNs to print, and don't want to see each DGN in the view display, then using the .NET API as it was designed to be used, e.g. emulating Print Organizer and leaving UseWorkerMicroStation=True, is the right choice.  Expect CreatePrintDefinitions to be an expensive method when first invoked, there's no way around that.

    Also note that Print Organizer has its own set of key-ins, so you may be able to make use of those.

          
    .

  • Yes, when UseWorerMicroStation=False, the API most certainly disturbs the active session

    My bad. That False should have been a True.

    If UseWorkerMicrostation is left unchanged, with default value true, the main thread will start the new process and this operation will block the UI for 15 seconds. From my point of view, that is quite a disturbance.

  • Another option would be to use variable print definitions (as named in the user interface and documentation).  They are referred to as "query print definitions" in the API.  Setting EnableQueryPrintDefinitions=True immediately after the print set is constructed would force them to be used instead of standard print definitions.

    You would want to read up on variable print definitions before going that route, making sure you understand the difference between them and standard print definitions.  Even through they already have two names, what they should have been called is "print-style-dependent print definitions".  The gist is the print definition consists of only a DGN file name, an optional model name, and a print style.  The print style is required, and is applied when the print definition is printed/previewed may result in one or more plots.  Setting properties like paper size, scale, etc. is not possible prior to printing; everything has to come from the print style.

    As far as I recall, there are also no SDK examples that demonstrate use of query print definitions.  They're pretty simple, though, not having any properties to speak of.  All the IPrintSet methods work the same way regardless of what types of print definitions are in the set.

    One advantage of variable print definitions is that the CreatePrintDefinitions method is very fast.  There's no need to load the DGN at that time.  The DGN isn't loaded until print/preview time, during which the state collection and printing operations are combined.

    The use of variable print definitions can be seen in the MicroStation sheet index feature.  Invoking Print Organizer from the sheet index requires a print style to be selected, after which the Print Organizer window comes up very quickly with the list of sheets from the index.  The worker process doesn't spin up until printing/previewing is initiated.

    But this really just boils down to when the time delay is going to occur.  At some point, no matter what technique you use, the main thread of the interactive session is going to be blocked for a significant period of time.  That's the nature of the beast.

          
    .

Reply
  • Another option would be to use variable print definitions (as named in the user interface and documentation).  They are referred to as "query print definitions" in the API.  Setting EnableQueryPrintDefinitions=True immediately after the print set is constructed would force them to be used instead of standard print definitions.

    You would want to read up on variable print definitions before going that route, making sure you understand the difference between them and standard print definitions.  Even through they already have two names, what they should have been called is "print-style-dependent print definitions".  The gist is the print definition consists of only a DGN file name, an optional model name, and a print style.  The print style is required, and is applied when the print definition is printed/previewed may result in one or more plots.  Setting properties like paper size, scale, etc. is not possible prior to printing; everything has to come from the print style.

    As far as I recall, there are also no SDK examples that demonstrate use of query print definitions.  They're pretty simple, though, not having any properties to speak of.  All the IPrintSet methods work the same way regardless of what types of print definitions are in the set.

    One advantage of variable print definitions is that the CreatePrintDefinitions method is very fast.  There's no need to load the DGN at that time.  The DGN isn't loaded until print/preview time, during which the state collection and printing operations are combined.

    The use of variable print definitions can be seen in the MicroStation sheet index feature.  Invoking Print Organizer from the sheet index requires a print style to be selected, after which the Print Organizer window comes up very quickly with the list of sheets from the index.  The worker process doesn't spin up until printing/previewing is initiated.

    But this really just boils down to when the time delay is going to occur.  At some point, no matter what technique you use, the main thread of the interactive session is going to be blocked for a significant period of time.  That's the nature of the beast.

          
    .

Children