Skip to content

Commit

Permalink
Fix Navisworks and others progress by yielding to UI thread (#465)
Browse files Browse the repository at this point in the history
* Navisworks needs proper Async to update UI thread inline

* Tested Autocad and Rhino

* format and fix

* ArcGIS should yield too

* async/await for Tekla and ETABs
  • Loading branch information
adamhathcock authored Dec 31, 2024
1 parent dcc29f3 commit 95b3731
Show file tree
Hide file tree
Showing 13 changed files with 40 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Speckle.Connectors.ArcGIS.HostApp.Extensions;
using Speckle.Connectors.ArcGIS.Utils;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Extensions;
using Speckle.Connectors.Common.Operations;
Expand All @@ -24,7 +23,6 @@ namespace Speckle.Connectors.ArcGis.Operations.Send;
public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
{
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
private readonly ISendConversionCache _sendConversionCache;
private readonly ArcGISLayerUnpacker _layerUnpacker;
private readonly ArcGISColorUnpacker _colorUnpacker;
private readonly IConverterSettingsStore<ArcGISConversionSettings> _converterSettings;
Expand All @@ -33,7 +31,6 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
private readonly MapMembersUtils _mapMemberUtils;

public ArcGISRootObjectBuilder(
ISendConversionCache sendConversionCache,
ArcGISLayerUnpacker layerUnpacker,
ArcGISColorUnpacker colorUnpacker,
IConverterSettingsStore<ArcGISConversionSettings> converterSettings,
Expand All @@ -43,7 +40,6 @@ public ArcGISRootObjectBuilder(
MapMembersUtils mapMemberUtils
)
{
_sendConversionCache = sendConversionCache;
_layerUnpacker = layerUnpacker;
_colorUnpacker = colorUnpacker;
_converterSettings = converterSettings;
Expand All @@ -53,9 +49,9 @@ MapMembersUtils mapMemberUtils
_mapMemberUtils = mapMemberUtils;
}

public RootObjectBuilderResult Build(
public async Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<ADM.MapMember> layers,
SendInfo sendInfo,
SendInfo __,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
Expand Down Expand Up @@ -171,6 +167,7 @@ out ObjectReference? value
}

onOperationProgressed.Report(new("Converting", (double)++count / layers.Count));
await Task.Yield();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace Speckle.Connectors.Autocad.Operations.Send;

public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadRootObject>
public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<AutocadRootObject>
{
private readonly IRootToSpeckleConverter _converter;
private readonly string[] _documentPathSeparator = ["\\"];
Expand Down Expand Up @@ -58,7 +58,7 @@ It is already simplified but has many different references since it is a builder
proxy classes yet. So I'm supressing this one now!!!
"""
)]
public RootObjectBuilderResult Build(
public override RootObjectBuilderResult Build(
IReadOnlyList<AutocadRootObject> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ICsiApplicationService csiApplicationService
_csiApplicationService = csiApplicationService;
}

public RootObjectBuilderResult Build(
public async Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<ICsiWrapper> csiObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down Expand Up @@ -70,6 +70,7 @@ CancellationToken cancellationToken

count++;
onOperationProgressed.Report(new("Converting", (double)count / csiObjects.Count));
await Task.Yield();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ IElementSelectionService selectionService
private void OnSelectionChange(object? o, EventArgs eventArgs) =>
_appIdleManager.SubscribeToIdle(nameof(NavisworksSelectionBinding), async () => await UpdateSelectionAsync());

private void UpdateSelection()
{
SelectionInfo selInfo = GetSelection();
Parent.Send(SELECTION_EVENT, selInfo);
}

private async Task UpdateSelectionAsync()
{
var selInfo = GetSelection();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ await scope
.Execute(
navisworksModelItems,
modelCard.GetSendInfo(_speckleApplication.Slug),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCard.ModelCardId!, token),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCard.ModelCardId.NotNull(), token),
token
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ IElementSelectionService elementSelectionService

internal NavisworksConversionSettings GetCurrentSettings() => converterSettings.Current;

public RootObjectBuilderResult Build(
public async Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down Expand Up @@ -79,6 +79,7 @@ CancellationToken cancellationToken
results.Add(converted);
processedCount++;
onOperationProgressed.Report(new CardProgress("Converting", (double)processedCount / totalCount));
await Task.Yield();
}

if (results.All(x => x.Status == Status.ERROR))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,4 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)Operations\_Receive\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ public class RevitRootObjectBuilder(
SendCollectionManager sendCollectionManager,
ILogger<RevitRootObjectBuilder> logger,
RevitToSpeckleCacheSingleton revitToSpeckleCacheSingleton
) : IRootObjectBuilder<ElementId>
) : RootObjectBuilderBase<ElementId>
{
// POC: SendSelection and RevitConversionContextStack should be interfaces, former needs interfaces

public RootObjectBuilderResult Build(
public override RootObjectBuilderResult Build(
IReadOnlyList<ElementId> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ ISdkActivityFactory activityFactory
_activityFactory = activityFactory;
}

public RootObjectBuilderResult Build(
public async Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<RhinoObject> rhinoObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down Expand Up @@ -108,6 +108,7 @@ CancellationToken cancellationToken

++count;
onOperationProgressed.Report(new("Converting", (double)count / atomicObjects.Count));
await Task.Yield();

// NOTE: useful for testing ui states, pls keep for now so we can easily uncomment
// Thread.Sleep(550);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ TeklaMaterialUnpacker materialUnpacker
_materialUnpacker = materialUnpacker;
}

public RootObjectBuilderResult Build(
public async Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<TSM.ModelObject> teklaObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down Expand Up @@ -73,6 +73,7 @@ CancellationToken cancellationToken

++count;
onOperationProgressed.Report(new("Converting", (double)count / teklaObjects.Count));
await Task.Yield();
}
}

Expand Down
5 changes: 4 additions & 1 deletion DUI3/Speckle.Connectors.DUI/Models/Card/ModelCardProgress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
/// Progress value between 0 and 1 to calculate UI progress bar width.
/// If it is null it will swooshing on UI.
/// </summary>
public record ModelCardProgress(string ModelCardId, string Status, double? Progress);
public record ModelCardProgress(string ModelCardId, string Status, double? Progress)
{
public override string ToString() => $"{ModelCardId} - {Status} - {Progress}";
}
19 changes: 18 additions & 1 deletion Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,24 @@ namespace Speckle.Connectors.Common.Builders;

public interface IRootObjectBuilder<in T>
{
public RootObjectBuilderResult Build(
public Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<T> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
);
}

public abstract class RootObjectBuilderBase<T> : IRootObjectBuilder<T>
{
public Task<RootObjectBuilderResult> BuildAsync(
IReadOnlyList<T> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
) => Task.FromResult(Build(objects, sendInfo, onOperationProgressed, cancellationToken));

public abstract RootObjectBuilderResult Build(
IReadOnlyList<T> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
Expand Down
4 changes: 2 additions & 2 deletions Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public async Task<SendOperationResult> Execute(
CancellationToken ct = default
)
{
var buildResult = await threadContext.RunOnMain(
() => rootObjectBuilder.Build(objects, sendInfo, onOperationProgressed, ct)
var buildResult = await threadContext.RunOnMainAsync(
async () => await rootObjectBuilder.BuildAsync(objects, sendInfo, onOperationProgressed, ct)
);

// POC: Jonathon asks on behalf of willow twin - let's explore how this can work
Expand Down

0 comments on commit 95b3731

Please sign in to comment.