Compare commits

...

6 Commits

Author SHA1 Message Date
oguzhankoral 055cdb67a7 revert rest 2025-02-06 15:54:02 +00:00
oguzhankoral bc57632f3d revert autocad 2025-02-06 15:51:11 +00:00
oguzhankoral d443d2149b revert rhino 2025-02-06 15:49:01 +00:00
oguzhankoral b8edac1072 Merge remote-tracking branch 'origin/dev' into oguzhan/fix-threading 2025-02-06 15:19:08 +00:00
oguzhankoral 155d53c740 untangle revit 2025-02-06 15:18:27 +00:00
oguzhankoral 90c9308b8b Fix threading bug 2025-02-06 14:17:00 +00:00
20 changed files with 130 additions and 96 deletions
@@ -53,7 +53,7 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
_colorManager = colorManager;
}
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
@@ -226,7 +226,7 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
// TODO: validated a correct set regarding bakedobject ids
return new(bakedObjectIds, results);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, results));
}
private IReadOnlyCollection<LocalToGlobalMap> GetObjectsToConvert(Base rootObject)
@@ -49,7 +49,7 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
_mapMemberUtils = mapMemberUtils;
}
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<ADM.MapMember> layers,
SendInfo __,
IProgress<CardProgress> onOperationProgressed,
@@ -31,7 +31,7 @@ public class AutocadHostObjectBuilder(
RootObjectUnpacker rootObjectUnpacker
) : IHostObjectBuilder
{
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
@@ -139,7 +139,7 @@ public class AutocadHostObjectBuilder(
results.UnionWith(groupResults);
}
return new HostObjectBuilderResult(bakedObjectIds, results);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, results));
}
private void PreReceiveDeepClean(string baseLayerPrefix)
@@ -16,7 +16,7 @@ using Speckle.Sdk.Models.Instances;
namespace Speckle.Connectors.Autocad.Operations.Send;
public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<AutocadRootObject>
public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadRootObject>
{
private readonly IRootToSpeckleConverter _converter;
private readonly string[] _documentPathSeparator = ["\\"];
@@ -58,7 +58,7 @@ public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<Autoc
proxy classes yet. So I'm supressing this one now!!!
"""
)]
public override RootObjectBuilderResult Build(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<AutocadRootObject> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -133,7 +133,7 @@ public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<Autoc
// add any additional properties (most likely from verticals)
AddAdditionalProxiesToRoot(root);
return new RootObjectBuilderResult(root, results);
return Task.FromResult(new RootObjectBuilderResult(root, results));
}
}
@@ -68,7 +68,7 @@ public class CsiRootObjectBuilder : IRootObjectBuilder<ICsiWrapper>
/// 2. Converts each object with caching and progress tracking
/// 3. Creates proxies for materials and sections
/// </remarks>
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<ICsiWrapper> csiObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -41,7 +41,7 @@ public class NavisworksRootObjectBuilder(
/// <param name="cancellationToken">Token to cancel the operation.</param>
/// <returns>A result containing the root collection and conversion results.</returns>
/// <exception cref="SpeckleException">Thrown when no objects can be converted.</exception>
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -1,4 +1,5 @@
using Autodesk.Revit.DB;
using Revit.Async;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
@@ -129,38 +130,46 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
return;
}
HighlightObjectsOnView(elementIds);
await HighlightObjectsOnView(elementIds);
}
/// <summary>
/// Highlights the objects from the given ids.
/// </summary>
/// <param name="objectIds"> UniqueId's of the DB.Elements.</param>
public Task HighlightObjects(IReadOnlyList<string> objectIds)
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
{
var activeUIDoc =
_revitContext.UIApplication?.ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
HighlightObjectsOnView(
objectIds
.Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid))
.Where(el => el is not null)
.Cast<ElementId>()
.ToList()
);
return Task.CompletedTask;
await HighlightObjectsOnView(
objectIds
.Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid))
.Where(el => el is not null)
.Cast<ElementId>()
.ToList()
)
.ConfigureAwait(false);
}
private void HighlightObjectsOnView(List<ElementId> objectIds)
private async Task HighlightObjectsOnView(List<ElementId> objectIds)
{
// POC: don't know if we can rely on storing the ActiveUIDocument, hence getting it each time
var activeUIDoc =
_revitContext.UIApplication?.ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
activeUIDoc.Selection.SetElementIds(objectIds);
activeUIDoc.ShowElements(objectIds);
;
await RevitTask
.RunAsync(() =>
{
activeUIDoc.Selection.SetElementIds(objectIds);
activeUIDoc.ShowElements(objectIds);
})
.ConfigureAwait(false);
// activeUIDoc.Selection.SetElementIds(objectIds);
// activeUIDoc.ShowElements(objectIds);
// ;
}
}
@@ -1,6 +1,7 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI.Events;
using Revit.Async;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -83,20 +84,23 @@ internal sealed class RevitDocumentStore : DocumentModelStore
return;
}
using Transaction t = new(doc, "Speckle Write State");
t.Start();
using DataStorage ds = GetSettingsDataStorage(doc) ?? DataStorage.Create(doc);
RevitTask.RunAsync(() =>
{
using Transaction t = new(doc, "Speckle Write State");
t.Start();
using DataStorage ds = GetSettingsDataStorage(doc) ?? DataStorage.Create(doc);
using Entity stateEntity = new(_documentModelStorageSchema.GetSchema());
string serializedModels = Serialize();
stateEntity.Set("contents", serializedModels);
using Entity stateEntity = new(_documentModelStorageSchema.GetSchema());
string serializedModels = Serialize();
stateEntity.Set("contents", serializedModels);
using Entity idEntity = new(_idStorageSchema.GetSchema());
idEntity.Set("Id", s_revitDocumentStoreId);
using Entity idEntity = new(_idStorageSchema.GetSchema());
idEntity.Set("Id", s_revitDocumentStoreId);
ds.SetEntity(idEntity);
ds.SetEntity(stateEntity);
t.Commit();
ds.SetEntity(idEntity);
ds.SetEntity(stateEntity);
t.Commit();
});
}
protected override void LoadState()
@@ -5,6 +5,7 @@ using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Instances;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
@@ -33,6 +34,7 @@ public sealed class RevitHostObjectBuilder(
RevitMaterialBaker materialBaker,
RootObjectUnpacker rootObjectUnpacker,
ILogger<RevitHostObjectBuilder> logger,
IThreadContext threadContext,
RevitToHostCacheSingleton revitToHostCacheSingleton,
ITypedConverter<
(Base atomicObject, IReadOnlyCollection<Matrix4x4> matrix),
@@ -40,7 +42,18 @@ public sealed class RevitHostObjectBuilder(
> localToGlobalDirectShapeConverter
) : IHostObjectBuilder, IDisposable
{
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
) =>
threadContext.RunOnMainAsync(
() => Task.FromResult(BuildSync(rootObject, projectName, modelName, onOperationProgressed, cancellationToken))
);
private HostObjectBuilderResult BuildSync(
Base rootObject,
string projectName,
string modelName,
@@ -5,6 +5,7 @@ using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Extensions;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Converters.Common;
@@ -21,14 +22,22 @@ public class RevitRootObjectBuilder(
IConverterSettingsStore<RevitConversionSettings> converterSettings,
ISendConversionCache sendConversionCache,
ElementUnpacker elementUnpacker,
IThreadContext threadContext,
SendCollectionManager sendCollectionManager,
ILogger<RevitRootObjectBuilder> logger,
RevitToSpeckleCacheSingleton revitToSpeckleCacheSingleton
) : RootObjectBuilderBase<ElementId>
) : IRootObjectBuilder<ElementId>
{
// POC: SendSelection and RevitConversionContextStack should be interfaces, former needs interfaces
public override RootObjectBuilderResult Build(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<ElementId> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken ct = default
) => threadContext.RunOnMainAsync(() => Task.FromResult(BuildSync(objects, sendInfo, onOperationProgressed, ct)));
private RootObjectBuilderResult BuildSync(
IReadOnlyList<ElementId> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -61,7 +61,7 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
}
#pragma warning disable CA1506
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
#pragma warning restore CA1506
Base rootObject,
string projectName,
@@ -237,7 +237,7 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
}
_converterSettings.Current.Document.Views.Redraw();
return new HostObjectBuilderResult(bakedObjectIds, conversionResults);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, conversionResults));
}
private void PreReceiveDeepClean(string baseLayerName)
@@ -60,7 +60,7 @@ public class RhinoRootObjectBuilder : IRootObjectBuilder<RhinoObject>
_activityFactory = activityFactory;
}
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<RhinoObject> rhinoObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -43,7 +43,7 @@ public class TeklaRootObjectBuilder : IRootObjectBuilder<TSM.ModelObject>
_materialUnpacker = materialUnpacker;
}
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<TSM.ModelObject> teklaObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -124,25 +124,22 @@ public sealed class BrowserBridge : IBrowserBridge
//don't wait for browser runs on purpose
public void RunMethod(string methodName, string requestId, string methodArgs) =>
_threadContext
.RunOnThreadAsync(
async () =>
{
var task = await _topLevelExceptionHandler
.CatchUnhandledAsync(async () =>
{
var result = await ExecuteMethod(methodName, methodArgs).ConfigureAwait(false);
string resultJson = _jsonSerializer.Serialize(result);
NotifyUIMethodCallResultReady(requestId, resultJson);
})
.ConfigureAwait(false);
if (task.Exception is not null)
.RunOnWorkerAsync(async () =>
{
var task = await _topLevelExceptionHandler
.CatchUnhandledAsync(async () =>
{
string resultJson = SerializeFormattedException(task.Exception);
var result = await ExecuteMethod(methodName, methodArgs).ConfigureAwait(false);
string resultJson = _jsonSerializer.Serialize(result);
NotifyUIMethodCallResultReady(requestId, resultJson);
}
},
_threadOptions.RunCommandsOnMainThread
)
})
.ConfigureAwait(false);
if (task.Exception is not null)
{
string resultJson = SerializeFormattedException(task.Exception);
NotifyUIMethodCallResultReady(requestId, resultJson);
}
})
.FireAndForget();
/// <summary>
@@ -17,7 +17,7 @@ public interface IHostObjectBuilder
/// <returns> List of application ids.</returns> // POC: Where we will return these ids will matter later when we target to also cache received application ids.
/// <remarks>Project and model name are needed for now to construct host app objects into related layers or filters.
/// POC: we might consider later to have HostObjectBuilderContext? that might hold all possible data we will need.</remarks>
HostObjectBuilderResult Build(
Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
@@ -6,7 +6,7 @@ namespace Speckle.Connectors.Common.Builders;
public interface IRootObjectBuilder<in T>
{
public Task<RootObjectBuilderResult> BuildAsync(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<T> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -14,21 +14,21 @@ public interface IRootObjectBuilder<in T>
);
}
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,
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,
// CancellationToken cancellationToken
// );
// }
public record RootObjectBuilderResult(Base RootObject, IEnumerable<SendConversionResult> ConversionResults);
@@ -16,8 +16,7 @@ public sealed class ReceiveOperation(
ISdkActivityFactory activityFactory,
IOperations operations,
IClientFactory clientFactory,
IThreadContext threadContext,
IThreadOptions threadOptions
IThreadContext threadContext
)
{
public async Task<HostObjectBuilderResult> Execute(
@@ -40,10 +39,13 @@ public sealed class ReceiveOperation(
);
// 4 - Convert objects
HostObjectBuilderResult res = await threadContext.RunOnThread(
() => ConvertObjects(commitObject, receiveInfo, onOperationProgressed, cancellationToken),
threadOptions.RunReceiveBuildOnMainThread
);
HostObjectBuilderResult res = await ConvertObjects(
commitObject,
receiveInfo,
onOperationProgressed,
cancellationToken
)
.ConfigureAwait(false);
await apiClient.Version.Received(
new(version.id, receiveInfo.ProjectId, receiveInfo.SourceApplication),
@@ -75,7 +77,7 @@ public sealed class ReceiveOperation(
return commitObject;
}
private HostObjectBuilderResult ConvertObjects(
private async Task<HostObjectBuilderResult> ConvertObjects(
Base commitObject,
ReceiveInfo receiveInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -92,13 +94,9 @@ public sealed class ReceiveOperation(
try
{
HostObjectBuilderResult res = hostObjectBuilder.Build(
commitObject,
receiveInfo.ProjectName,
receiveInfo.ModelName,
onOperationProgressed,
cancellationToken
);
HostObjectBuilderResult res = await hostObjectBuilder
.Build(commitObject, receiveInfo.ProjectName, receiveInfo.ModelName, onOperationProgressed, cancellationToken)
.ConfigureAwait(false);
conversionActivity?.SetStatus(SdkActivityStatusCode.Ok);
return res;
}
@@ -31,9 +31,7 @@ public sealed class SendOperation<T>(
CancellationToken ct = default
)
{
var buildResult = await threadContext.RunOnMainAsync(
async () => await rootObjectBuilder.BuildAsync(objects, sendInfo, onOperationProgressed, ct)
);
var buildResult = await rootObjectBuilder.Build(objects, sendInfo, onOperationProgressed, ct);
// POC: Jonathon asks on behalf of willow twin - let's explore how this can work
// buildResult.RootObject["@report"] = new Report { ConversionResults = buildResult.ConversionResults };
@@ -90,7 +90,14 @@ public abstract class ThreadContext : IThreadContext
}
else
{
await RunMainAsync(action);
if (useMain)
{
await RunMainAsync(action);
}
else
{
await action();
}
}
}
}
@@ -8,5 +8,4 @@ namespace Speckle.Connectors.Common.Threading;
public class ThreadOptions(ISpeckleApplication speckleApplication) : IThreadOptions
{
public bool RunReceiveBuildOnMainThread => speckleApplication.HostApplication != HostApplications.Rhino.Name;
public bool RunCommandsOnMainThread => speckleApplication.HostApplication != HostApplications.ArcGIS.Name;
}