From 676a7e8e2536589c8ce564a4d81cee4651110538 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 17 Dec 2024 15:04:27 +0000 Subject: [PATCH] rationalize NW and usage of cancellation token --- .../HostApp/ArcGISLayerUnpacker.cs | 4 +- .../Receive/ArcGISHostObjectBuilder.cs | 2 +- .../Send/ArcGISRootObjectBuilder.cs | 47 +++++-------------- .../Send/AutocadRootObjectBaseBuilder.cs | 4 +- .../Operations/Send/CsiRootObjectBuilder.cs | 4 +- .../NavisworksBasicConnectorBinding.cs | 17 ++----- .../Bindings/NavisworksSelectionBinding.cs | 5 +- .../Bindings/NavisworksSendBinding.cs | 5 -- .../NavisworksConnectorServiceRegistration.cs | 3 +- .../HostApp/NavisworksDocumentEvents.cs | 5 -- .../Send/NavisworksRootObjectBuilder.cs | 6 +-- .../Plugin/DockableConnectorPane.cs | 3 -- .../Operations/Send/RevitRootObjectBuilder.cs | 4 +- .../Operations/Send/RhinoRootObjectBuilder.cs | 4 +- .../Operations/Send/TeklaRootObjectBuilder.cs | 4 +- .../Builders/IRootObjectBuilder.cs | 3 +- .../Operations/SendOperation.cs | 2 +- 17 files changed, 43 insertions(+), 79 deletions(-) diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISLayerUnpacker.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISLayerUnpacker.cs index b8955f895..7f68b03d3 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISLayerUnpacker.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISLayerUnpacker.cs @@ -18,7 +18,7 @@ public class ArcGISLayerUnpacker /// /// List of layers containing objects. /// Thrown when this method is *not* called on the MCT, because this method accesses mapmember fields - public async Task> UnpackSelectionAsync( + public List UnpackSelection( IEnumerable mapMembers, Collection parentCollection, List? objects = null @@ -37,7 +37,7 @@ public class ArcGISLayerUnpacker Collection containerCollection = CreateAndCacheMapMemberCollection(mapMember, true); parentCollection.elements.Add(containerCollection); - await UnpackSelectionAsync(container.Layers, containerCollection, objects).ConfigureAwait(false); + UnpackSelection(container.Layers, containerCollection, objects); break; default: diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/ArcGISHostObjectBuilder.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/ArcGISHostObjectBuilder.cs index 06edc2f86..5a9ce6512 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/ArcGISHostObjectBuilder.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/ArcGISHostObjectBuilder.cs @@ -99,7 +99,7 @@ CancellationToken cancellationToken try { obj = _localToGlobalConverterUtils.TransformObjects(objectToConvert.AtomicObject, objectToConvert.Matrix); - object? conversionResult = await QueuedTask.Run(() => _converter.Convert(obj)).ConfigureAwait(false); + object conversionResult = _converter.Convert(obj); string nestedLayerPath = $"{string.Join("\\", path)}"; diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs index c5c3ca855..51bd4eafd 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs @@ -1,6 +1,5 @@ using ArcGIS.Core.Data.Raster; using ArcGIS.Core.Geometry; -using ArcGIS.Desktop.Framework.Threading.Tasks; using Microsoft.Extensions.Logging; using Speckle.Connectors.ArcGIS.HostApp; using Speckle.Connectors.ArcGIS.HostApp.Extensions; @@ -54,10 +53,11 @@ MapMembersUtils mapMemberUtils _mapMemberUtils = mapMemberUtils; } - public async Task Build( + public RootObjectBuilderResult Build( IReadOnlyList layers, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ) { // TODO: add a warning if Geographic CRS is set @@ -102,9 +102,7 @@ IProgress onOperationProgressed IEnumerable layersOrdered = _mapMemberUtils.GetMapMembersInOrder(map, layers); using (var _ = _activityFactory.Start("Unpacking selection")) { - unpackedLayers = await QueuedTask - .Run(() => _layerUnpacker.UnpackSelectionAsync(layersOrdered, rootCollection)) - .ConfigureAwait(false); + unpackedLayers = _layerUnpacker.UnpackSelection(layersOrdered, rootCollection); } List results = new(unpackedLayers.Count); @@ -114,7 +112,7 @@ IProgress onOperationProgressed int count = 0; foreach (ADM.MapMember layer in unpackedLayers) { - ct.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); string layerApplicationId = layer.GetSpeckleApplicationId(); try @@ -140,21 +138,15 @@ out ObjectReference? value switch (layer) { case ADM.FeatureLayer featureLayer: - List convertedFeatureLayerObjects = await QueuedTask - .Run(() => ConvertFeatureLayerObjectsAsync(featureLayer)) - .ConfigureAwait(false); + List convertedFeatureLayerObjects = ConvertFeatureLayerObjects(featureLayer); layerCollection.elements.AddRange(convertedFeatureLayerObjects); break; case ADM.RasterLayer rasterLayer: - List convertedRasterLayerObjects = await QueuedTask - .Run(() => ConvertRasterLayerObjectsAsync(rasterLayer)) - .ConfigureAwait(false); + List convertedRasterLayerObjects = ConvertRasterLayerObjects(rasterLayer); layerCollection.elements.AddRange(convertedRasterLayerObjects); break; case ADM.LasDatasetLayer lasDatasetLayer: - List convertedLasDatasetObjects = await QueuedTask - .Run(() => ConvertLasDatasetLayerObjectsAsync(lasDatasetLayer)) - .ConfigureAwait(false); + List convertedLasDatasetObjects = ConvertLasDatasetLayerObjects(lasDatasetLayer); layerCollection.elements.AddRange(convertedLasDatasetObjects); break; default: @@ -193,13 +185,10 @@ out ObjectReference? value return new RootObjectBuilderResult(rootCollection, results); } - private async Task> ConvertFeatureLayerObjectsAsync(ADM.FeatureLayer featureLayer) + private List ConvertFeatureLayerObjects(ADM.FeatureLayer featureLayer) { string layerApplicationId = featureLayer.GetSpeckleApplicationId(); List convertedObjects = new(); - await QueuedTask - .Run(() => - { // store the layer renderer for color unpacking _colorUnpacker.StoreRendererAndFields(featureLayer); @@ -225,41 +214,31 @@ await QueuedTask } } } - }) - .ConfigureAwait(false); + return convertedObjects; } // POC: raster colors are stored as mesh vertex colors in RasterToSpeckleConverter. Should probably move to color unpacker. - private async Task> ConvertRasterLayerObjectsAsync(ADM.RasterLayer rasterLayer) + private List ConvertRasterLayerObjects(ADM.RasterLayer rasterLayer) { string layerApplicationId = rasterLayer.GetSpeckleApplicationId(); List convertedObjects = new(); - await QueuedTask - .Run(() => - { Raster raster = rasterLayer.GetRaster(); Base converted = _rootToSpeckleConverter.Convert(raster); string applicationId = raster.GetSpeckleApplicationId(layerApplicationId); converted.applicationId = applicationId; convertedObjects.Add(converted); - }) - .ConfigureAwait(false); - return convertedObjects; } - private async Task> ConvertLasDatasetLayerObjectsAsync(ADM.LasDatasetLayer lasDatasetLayer) + private List ConvertLasDatasetLayerObjects(ADM.LasDatasetLayer lasDatasetLayer) { string layerApplicationId = lasDatasetLayer.GetSpeckleApplicationId(); List convertedObjects = new(); try { - await QueuedTask - .Run(() => - { // store the layer renderer for color unpacking _colorUnpacker.StoreRenderer(lasDatasetLayer); @@ -281,8 +260,6 @@ await QueuedTask } } } - }) - .ConfigureAwait(false); } catch (ACD.Exceptions.TinException ex) { diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs index 62290cec2..b1de30e12 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs @@ -61,7 +61,8 @@ proxy classes yet. So I'm supressing this one now!!! public RootObjectBuilderResult Build( IReadOnlyList objects, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ) { // 0 - Init the root @@ -93,6 +94,7 @@ IProgress onOperationProgressed int count = 0; foreach (var (entity, applicationId) in atomicObjects) { + cancellationToken.ThrowIfCancellationRequested(); using (var convertActivity = _activityFactory.Start("Converting object")) { // Create and add a collection for this entity if not done so already. diff --git a/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs b/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs index 3c14eb19f..07386452d 100644 --- a/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs +++ b/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs @@ -45,7 +45,8 @@ ICsiApplicationService csiApplicationService public RootObjectBuilderResult Build( IReadOnlyList csiObjects, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ) { using var activity = _activityFactory.Start("Build"); @@ -61,6 +62,7 @@ IProgress onOperationProgressed { foreach (ICsiWrapper csiObject in csiObjects) { + cancellationToken.ThrowIfCancellationRequested(); using var _2 = _activityFactory.Start("Convert"); var result = ConvertCSiObject(csiObject, rootObjectCollection, sendInfo.ProjectId); diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksBasicConnectorBinding.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksBasicConnectorBinding.cs index 62c0ffda0..6ad747f10 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksBasicConnectorBinding.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksBasicConnectorBinding.cs @@ -41,11 +41,8 @@ NavisworksDocumentEvents documentEvents public string GetConnectorVersion() => _speckleApplication.SpeckleVersion; - public DocumentInfo? GetDocumentInfo() => - Parent - .RunOnMainThreadAsync( - () => - Task.FromResult( + public DocumentInfo? GetDocumentInfo() + => NavisworksApp.ActiveDocument is null || NavisworksApp.ActiveDocument.Models.Count == 0 ? null : new DocumentInfo( @@ -53,9 +50,8 @@ NavisworksDocumentEvents documentEvents NavisworksApp.ActiveDocument.Title, NavisworksApp.ActiveDocument.GetHashCode().ToString() ) - ) - ) - .Result; + + ; public DocumentModelStore GetDocumentState() => _store; @@ -68,11 +64,6 @@ NavisworksDocumentEvents documentEvents public Task HighlightModel(string modelCardId) => Task.CompletedTask; public async Task HighlightObjects(IReadOnlyList objectIds) => - await Parent - .RunOnMainThreadAsync(async () => - { // TODO: Implement highlighting logic on main thread await Task.CompletedTask.ConfigureAwait(false); - }) - .ConfigureAwait(false); } diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSelectionBinding.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSelectionBinding.cs index 52389c16b..91915aa94 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSelectionBinding.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSelectionBinding.cs @@ -39,10 +39,7 @@ private void UpdateSelection() private async Task UpdateSelectionAsync() { - var selInfo = await Parent - .RunOnMainThreadAsync(() => Task.FromResult(GetSelection())) - .ConfigureAwait(false); - + var selInfo = GetSelection(); await Parent.Send(SELECTION_EVENT, selInfo).ConfigureAwait(false); } diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs index 8e5c15e3a..ee9bb0fce 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs @@ -87,9 +87,6 @@ public async Task Send(string modelCardId) using var activity = _activityFactory.Start(); try { - await Parent - .RunOnMainThreadAsync(async () => - { var modelCard = GetModelCard(modelCardId); using var scope = _serviceProvider.CreateScope(); @@ -106,8 +103,6 @@ await Parent await Commands .SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults) .ConfigureAwait(false); - }) - .ConfigureAwait(false); } catch (OperationCanceledException) { diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs index a1d398292..b906ddce4 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs @@ -9,6 +9,7 @@ using Speckle.Connectors.Common.Builders; using Speckle.Connectors.Common.Cancellation; using Speckle.Connectors.Common.Operations; +using Speckle.Connectors.Common.Threading; using Speckle.Connectors.DUI; using Speckle.Connectors.DUI.Bindings; using Speckle.Connectors.DUI.Bridge; @@ -27,7 +28,7 @@ public static void AddNavisworks(this IServiceCollection serviceCollection) { // Register Core functionality serviceCollection.AddConnectorUtils(); - serviceCollection.AddDUI(); + serviceCollection.AddDUI(); serviceCollection.AddDUIView(); // Register bindings diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/HostApp/NavisworksDocumentEvents.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/HostApp/NavisworksDocumentEvents.cs index 26fed81ee..db87e7e00 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/HostApp/NavisworksDocumentEvents.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/HostApp/NavisworksDocumentEvents.cs @@ -102,9 +102,6 @@ private async Task ProcessModelStateChangeAsync() try { - await _parent - .RunOnMainThreadAsync(async () => - { var store = _serviceProvider.GetRequiredService(); var basicBinding = _serviceProvider.GetRequiredService(); var commands = (basicBinding as NavisworksBasicConnectorBinding)?.Commands; @@ -123,8 +120,6 @@ await _parent { await commands.NotifyDocumentChanged().ConfigureAwait(false); } - }) - .ConfigureAwait(false); } finally { diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs index f58d59377..a099cb4fb 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs @@ -28,11 +28,11 @@ IElementSelectionService elementSelectionService { internal NavisworksConversionSettings GetCurrentSettings() => converterSettings.Current; - public Task Build( + public RootObjectBuilderResult Build( IReadOnlyList navisworksModelItems, SendInfo sendInfo, IProgress onOperationProgressed, - CancellationToken cancellationToken = default + CancellationToken cancellationToken ) { using var activity = activityFactory.Start("Build"); @@ -151,7 +151,7 @@ public Task Build( // 8. Finalize and return rootObjectCollection.elements = finalElements; - return Task.FromResult(new RootObjectBuilderResult(rootObjectCollection, results)); + return new RootObjectBuilderResult(rootObjectCollection, results); } private SendConversionResult ConvertNavisworksItem( diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Plugin/DockableConnectorPane.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Plugin/DockableConnectorPane.cs index d6022ca75..b779afe43 100644 --- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Plugin/DockableConnectorPane.cs +++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Plugin/DockableConnectorPane.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.DependencyInjection; using Speckle.Connector.Navisworks.DependencyInjection; using Speckle.Connectors.Common; -using Speckle.Connectors.DUI; using Speckle.Connectors.DUI.WebView; using Speckle.Converter.Navisworks.DependencyInjection; using Speckle.Sdk.Host; @@ -42,8 +41,6 @@ public override Control CreateControlPane() Container = services.BuildServiceProvider(); - Container.UseDUI(); - var u = Container.GetRequiredService(); var speckleHost = new ElementHost { AutoSize = true, Child = u }; diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs index 287214e2a..0e1fcd55e 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs @@ -31,7 +31,8 @@ RevitToSpeckleCacheSingleton revitToSpeckleCacheSingleton public RootObjectBuilderResult Build( IReadOnlyList objects, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ) { var doc = converterSettings.Current.Document; @@ -73,6 +74,7 @@ IProgress onOperationProgressed foreach (Element revitElement in atomicObjects) { + cancellationToken.ThrowIfCancellationRequested(); string applicationId = revitElement.UniqueId; string sourceType = revitElement.GetType().Name; try diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs index 1d15c5d3b..ceec97b2c 100644 --- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs +++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs @@ -63,7 +63,8 @@ ISdkActivityFactory activityFactory public RootObjectBuilderResult Build( IReadOnlyList rhinoObjects, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ) { using var activity = _activityFactory.Start("Build"); @@ -94,6 +95,7 @@ IProgress onOperationProgressed { foreach (RhinoObject rhinoObject in atomicObjects) { + cancellationToken.ThrowIfCancellationRequested(); using var _2 = _activityFactory.Start("Convert"); // handle layer diff --git a/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs b/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs index e7e4fef87..1f5bb8a2c 100644 --- a/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs +++ b/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs @@ -46,7 +46,8 @@ TeklaMaterialUnpacker materialUnpacker public RootObjectBuilderResult Build( IReadOnlyList teklaObjects, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ) { using var activity = _activityFactory.Start("Build"); @@ -64,6 +65,7 @@ IProgress onOperationProgressed { foreach (TSM.ModelObject teklaObject in teklaObjects) { + cancellationToken.ThrowIfCancellationRequested(); using var _2 = _activityFactory.Start("Convert"); var result = ConvertTeklaObject(teklaObject, rootObjectCollection, sendInfo.ProjectId); diff --git a/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs b/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs index c018b2b4d..747df3acd 100644 --- a/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs +++ b/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs @@ -9,7 +9,8 @@ public interface IRootObjectBuilder public RootObjectBuilderResult Build( IReadOnlyList objects, SendInfo sendInfo, - IProgress onOperationProgressed + IProgress onOperationProgressed, + CancellationToken cancellationToken ); } diff --git a/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs b/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs index 3d3021be2..7eb5d5c0a 100644 --- a/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs +++ b/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs @@ -32,7 +32,7 @@ public async Task Execute( ) { var buildResult = await threadContext.RunOnMain( - () => rootObjectBuilder.Build(objects, sendInfo, onOperationProgressed) + () => rootObjectBuilder.Build(objects, sendInfo, onOperationProgressed, ct) ); // POC: Jonathon asks on behalf of willow twin - let's explore how this can work