Добрый день, коллеги.
Я честно говоря, не знаю, с чем именно связано изменение поведения кода в Revit 2019, полагаю, что дело всё же в реализации ServiceHost самим фреймворком. Дело в том, что исходный код полагается на то, что методы сервиса и обработчик события OnIdling вызываются более-менее независимо, т.е. в методе сервиса (упрощенно) запускается:
lock (Locker)
{
TaskContainer.Instance.EnqueueTask(GetDocumentPath); // <- здесь запуск задачи GetDocumentPath
Monitor.Wait(Locker, WaitTimeout);// <- вот здесь ожидается, что где-то кто-то за отведенный промежуток времени вызовет Monitor.Pulse(Locker);
}
return currentDocumentPath;
Соответственно в обработчике событий вызывается Monitor.Pulse:
private void GetDocumentPath(UIApplication uiapp)
{
try
{
currentDocumentPath = uiapp.ActiveUIDocument.Document.PathName;
}
finally
{
lock (Locker)
{
Monitor.Pulse(Locker); //<- ТЫЦ!
}
}
}
Ну а сам этот код фактически вызывается из обработчика события OnIdling, который дергает сам Revit.
Всё вроде бы хорошо, но фактически событие OnIdling вызываться перестает, останавливаемся на строке
Monitor.Wait(Locker, WaitTimeout);
По таймауту сервис отваливается, а затем код успешно выполняется из обработчика события
Окей, так пусть же serviceHost открывается в отдельном потоке:
private const string ServiceUrlHttp = "http://localhost:9001/RevitExternalService";
private const string ServiceUrlTcp = "net.tcp://localhost:9002/RevitExternalService";
public Result OnStartup(UIControlledApplication application)
{
application.Idling += OnIdling;
try
{
Task.Factory.StartNew(() =>
{
var serviceHost = new ServiceHost(typeof(RevitExternalService), new Uri(ServiceUrlHttp), new Uri(ServiceUrlTcp));
serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior());
serviceHost.AddServiceEndpoint(typeof(IRevitExternalService), new BasicHttpBinding(), ServiceUrlHttp);
serviceHost.AddServiceEndpoint(typeof(IRevitExternalService), new NetTcpBinding(), ServiceUrlTcp);
serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
serviceHost.Open();
}, TaskCreationOptions.LongRunning);
}
catch (Exception ex)
{
//....
}
return Result.Succeeded;
}
Ну и собственно, теперь снова всё работает