Traditionally, AutoCAD .NET plugins work with geometry and the drawing database.
But modern workflows often require pulling data from the web —
for example, fetching design inputs, configuration, or geometry parameters from a service.
Since the AutoCAD .NET API is not thread-safe, you cannot call it directly
from a background thread. This becomes tricky when performing network I/O,
which is inherently asynchronous.
The solution:
- Perform network requests in a background task
(Task.RunorHttpClientasync calls). - Use
SynchronizationContext.Currentcaptured on the AutoCAD UI thread
to post results back. - Modify the AutoCAD drawing safely on the main thread.
Example: Drawing Lines from Web Data
We host a simple JSON file on GitHub Pages:
{
"lines": [
{ "start": { "x": 0, "y": 0, "z": 0 }, "end": { "x": 25, "y": 15, "z": 0 } },
{ "start": { "x": 10, "y": 5, "z": 0 }, "end": { "x": 40, "y": 30, "z": 0 } }
]
}
In AutoCAD, the command WEBLINES downloads this file and creates corresponding
Line entities in ModelSpace:
public async void CreateLinesFromWeb()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Capture AutoCAD main thread SynchronizationContext
System.Threading.SynchronizationContext uiContext =
Autodesk.AutoCAD.Runtime.SynchronizationContext.Current;
try
{
// Fetch and parse JSON in background
var lines = await Task.Run(async () =>
{
using HttpClient client = new HttpClient();
string url = "https://madhukarmoogala.github.io/linepoints.json";
string json = await client.GetStringAsync(url);
JsonDocument docRoot = JsonDocument.Parse(json);
var lineList = new System.Collections.Generic.List();
foreach (var lineElem in docRoot.RootElement.GetProperty("lines").EnumerateArray())
{
Point3d start = new Point3d(
lineElem.GetProperty("start").GetProperty("x").GetDouble(),
lineElem.GetProperty("start").GetProperty("y").GetDouble(),
lineElem.GetProperty("start").GetProperty("z").GetDouble()
);
Point3d end = new Point3d(
lineElem.GetProperty("end").GetProperty("x").GetDouble(),
lineElem.GetProperty("end").GetProperty("y").GetDouble(),
lineElem.GetProperty("end").GetProperty("z").GetDouble()
);
lineList.Add((start, end));
}
return lineList;
});
// Post back to UI thread to modify AutoCAD Database
uiContext.Post(_ =>
{
using (doc.LockDocument())
using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
{
BlockTable bt =
(BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
BlockTableRecord ms =
(BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite);
foreach (var linePair in lines)
{
Point3d start = linePair.start;
Point3d end = linePair.end;
Line line = new Line(start, end);
ms.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
ed.WriteMessage($"nCreated line from {start} → {end}");
}
tr.Commit();
ed.WriteMessage("nLines created successfully from web data.");
ed.PostCommandPrompt();
}
}, null);
}
catch (Exception ex)
{
ed.WriteMessage($"nError fetching/drawing lines: {ex.Message}");
}
}
This small pattern opens the door to connecting AutoCAD commands with
cloud services, APIs, and dynamic data — safely mixing modern async programming
with AutoCAD’s single-threaded API.

Leave a Reply