
Complete Code Example Available on GitHub:
https://github.com/BlueByteSystemsInc/SW_API_Tips_Tricks/tree/master/ReportProgress
When working with the SOLIDWORKS API, it’s common to encounter operations that take significant time—such as traversing large assemblies, analyzing complex parts, or batch processing files. Unlike some applications that allow multithreading for responsiveness, SOLIDWORKS operates primarily on a single-threaded model. This means traditional threading approaches aren’t ideal for providing user feedback on lengthy operations. However, SOLIDWORKS offers a built-in way to display progress and provide cancellation options through its own API, ensuring your application remains responsive and user-friendly.
Why Not Use Threads?
While you might instinctively think about using separate threads to keep your user interface responsive, SOLIDWORKS is inherently single-threaded. Interacting with the SOLIDWORKS API from multiple threads can lead to instability and unpredictable behavior, including crashes. Hence, relying on SOLIDWORKS’ native progress reporting tools is strongly recommended.
SOLIDWORKS’ Built-in Progress Reporting: UserProgressBar
SOLIDWORKS provides a straightforward mechanism for reporting progress to users via the UserProgressBar
interface. This built-in progress bar not only shows progress visually but also allows users to cancel ongoing tasks. The user can cancel an operation by pressing the Escape key.
Here’s how you can implement it effectively in your SOLIDWORKS API programs.
Example Implementation in C#
Let’s illustrate with a practical example. The following snippet demonstrates a typical scenario: performing repetitive, time-consuming operations (like face analysis) and reporting progress clearly to users:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
using BlueByte.SOLIDWORKS.Extensions; using SolidWorks.Interop.sldworks; using SolidWorks.Interop.swconst; using System; using System.IO; using System.Linq; namespace ReportProgress { public class Example { public static void Run() { // Launch a new instance of SOLIDWORKS var solidworksManager = new SOLIDWORKSInstanceManager(); var swApp = solidworksManager.GetNewInstance("/m", SOLIDWORKSInstanceManager.Year_e.Year2023, 160); swApp.Visible = true; // Locate and open the test file var currentLocation = new FileInfo(typeof(Example).Assembly.Location).Directory; var testFile = currentLocation.GetFiles() .FirstOrDefault(x => x.Name.Equals("tank_20lb_propane_&.SLDPRT", StringComparison.OrdinalIgnoreCase)); if (testFile == null) throw new FileNotFoundException("Could not find the specified part in the current directory."); int errors = 0, warnings = 0; var swModel = swApp.OpenDoc6(testFile.FullName, (int)swDocumentTypes_e.swDocPART, (int)swOpenDocOptions_e.swOpenDocOptions_Silent, "", ref errors, ref warnings); if (swModel == null) throw new InvalidOperationException("Failed to open the document."); bool repeat = true; while (repeat) { PerformOperationWithProgress(swApp, swModel); swApp.CloseDoc(swModel.GetTitle()); Console.WriteLine("\nOperation completed."); Console.Write("Do you want to repeat the process? (Y/N): "); repeat = Console.ReadLine()?.Trim().Equals("Y", StringComparison.OrdinalIgnoreCase) == true; if (repeat) { swModel = swApp.ActiveDoc as ModelDoc2; } } swApp.ExitApp(); Console.WriteLine("\nExiting. Press any key to close..."); Console.ReadKey(); } private static void PerformOperationWithProgress(SldWorks swApp, ModelDoc2 swModel) { swApp.GetUserProgressBar(out UserProgressBar swPrgBar); int maxProgress = 100000; // Example: set according to your actual workload swPrgBar.Start(0, maxProgress, "Performing face operations..."); for (int progressCounter = 1; progressCounter <= maxProgress; progressCounter++) { swPrgBar.UpdateTitle($"Processing item {progressCounter}/{maxProgress}..."); if (swPrgBar.UpdateProgress(progressCounter) == (int)swUpdateProgressError_e.swUpdateProgressError_UserCancel) { int response = swApp.SendMsgToUser2( "Would you like to cancel the operation?", (int)swMessageBoxIcon_e.swMbQuestion, (int)swMessageBoxBtn_e.swMbYesNo); if (response == (int)swMessageBoxResult_e.swMbHitYes) { swPrgBar.End(); Console.WriteLine("Operation canceled by user."); return; } } // Your long-running task logic here } swPrgBar.End(); Console.WriteLine("Operation completed successfully."); } } } |
Key Points in the Example:
- Initialization:
UserProgressBar
is started with a defined range and title. - Progress Updates: Call
UpdateProgress()
frequently within your loop or operation to keep users informed. - Handling Cancellation: The method returns a status indicating if a user has requested cancellation. You can then gracefully abort or confirm with the user.
- Completing the Task: Always call
End()
on your progress bar when finished or canceled.
Benefits of Using SOLIDWORKS’ Progress Bar:
- Immediate Feedback: Users visually track operation progress, improving user experience.
- Responsive Cancellation: Users can safely abort operations without risk to data integrity.
- Stable API Interactions: Avoids risks associated with threading, ensuring stability and compatibility with SOLIDWORKS’ single-threaded architecture.