Long-running operations, such as exporting Civil 3D corridors to solids, can cause workflows to appear unresponsive, especially in cloud-based or asynchronous environments. To address this, AutoCAD provides a heartbeat signal mechanism to indicate the application is still alive during lengthy tasks.
This post demonstrates how to implement a heartbeat mechanism while performing a complex operation: exporting corridors to solids using Civil 3D's Automation (DA) environment.
Thanks for Albert from Engineering to provide this suggestion.
Why Use a Heartbeat?
Automation (DA) environments often impose timeouts to ensure system stability. Without interaction during a long-running operation, DA might terminate the process, mistaking it for a hang. By signaling a heartbeat, you can inform DA that the process is active and prevent unintended termination.
Code Walkthrough
Below is the complete implementation of a corridor export command, including heartbeat signaling.
Key Features
- Heartbeat Signaling: Signals activity during long-running operations using AcApHeartSendBeat().
- Corridor Export: Exports corridors to solids while reporting progress and writing results to a file.
- Error Handling: Provides robust error and transaction management.
The Heartbeat Manager
The HeartbeatManager encapsulates the logic for sending heartbeat signals at regular intervals. It uses a background task to send the signal and gracefully handles cancellation when the process ends.
[DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl,
           EntryPoint = "?sendBeat@AcApHeart@@YAXXZ")]
private static extern void AcApHeartSendBeat();
private class HeartbeatManager : IDisposable
{
    private readonly CancellationTokenSource _cts;
    private readonly Task _heartbeatTask;
    public HeartbeatManager()
    {
        _cts = new CancellationTokenSource();
        _heartbeatTask = StartHeartbeat(_cts.Token);
    }
    private static Task StartHeartbeat(CancellationToken token)
    {
        return Task.Run(async () =>
        {
            while (!token.IsCancellationRequested)
            {
                AcApHeartSendBeat();
                await Task.Delay(100, token);
            }
        }, token);
    }
    public void Dispose()
    {
        _cts.Cancel();
        _heartbeatTask.Wait(1000);
        _cts.Dispose();
    }
}
Exporting Corridors to Solids
The ExportCorridor command demonstrates how to:
- Access Civil 3D corridors from the active document.
- Export these corridors to solids using ExportSolids.
- Write the results (handles of solids) to a text file.
Here’s the core command logic:
[CommandMethod("ExportCorridor")]
public void ExportCorridor()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    if (doc == null) return;
    using var heartbeat = new HeartbeatManager();
    try
    {
        ExportCorridorInternal(doc.Database, doc.Editor);
    }
    catch (Exception ex)
    {
        doc.Editor.WriteMessage($"\nError during corridor export: {ex.Message}");
    }
}
The Export Logic
The method ExportCorridorInternal performs the export by iterating through corridors, creating solids, and writing their handles to a file. It uses the ExportCorridorSolidsParams class to define export options.
private static void ExportCorridorInternal(Database database, Editor editor)
{
    var civilDoc = CivilApplication.ActiveDocument ?? throw new InvalidOperationException("No active Civil 3D document found.");
    var corridors = civilDoc.CorridorCollection;
    var exportOptions = CreateExportOptions();
    using (var transaction = database.TransactionManager.StartOpenCloseTransaction())
    {
        foreach (ObjectId corridorId in corridors)
        {
            var corridor = transaction.GetObject(corridorId, OpenMode.ForRead) as Corridor;
            if (corridor == null) continue;
            ObjectIdCollection solidIds = corridor.ExportSolids(exportOptions, null);
            File.Create(@"solids.txt").Close();
            using (var file = new StreamWriter(@"solids.txt", true))
            {
                foreach (var solidId in solidIds.Cast<ObjectId>())
                {
                    var solid = transaction.GetObject(solidId, OpenMode.ForRead) as Solid3d;
                    if (solid != null)
                    {
                        file.WriteLine(solidId.Handle.ToString());
                    }
                }
            }
            editor.WriteMessage($"\nExported {solidIds?.Count ?? 0} solids.");
        }
    }
}
Export Options
The CreateExportOptions method defines the parameters for the export operation, including what corridor components to export.
private static ExportCorridorSolidsParams CreateExportOptions()
{
    return new ExportCorridorSolidsParams
    {
        CreateSolidForShape = true,
        ExportShapes = true,
        ExportLinks = false,
        SweepSolidForShape = false
    };
}
Example Use Case
- 
Source Drawing: The command assumes a Civil 3D corridor exists in the drawing. 
 Example file:Corridor-5c.dwg(from Civil 3D tutorials).
- 
Command Execution: Run the command ExportCorridorin the Civil 3D environment.
- 
Output: A file named solids.txtwill be created, listing the handles of exported solids.
- 
Heartbeat: The system remains responsive throughout the process, signaling activity every 100ms. 
Example Use Case
- 
Source Drawing: The command assumes a Civil 3D corridor exists in the drawing. 
 Example file:Corridor-5c.dwg(from Civil 3D tutorials).
- 
Command Execution: Run the command ExportCorridorin the Civil 3D environment.
- 
Output: A file named solids.txtwill be created, listing the handles of exported solids.
- 
Heartbeat: The system remains responsive throughout the process, signaling activity every 100ms. 
The heartbeat mechanism ensures smooth execution of long-running tasks in Automation environments. This example demonstrates how to integrate it with Civil 3D or AutoCAD Automation API for corridor-to-solid export tasks.
With this approach, your applications can handle complex workflows while maintaining stability and preventing timeouts.
Try it out and let us know how it works for you!
 
