1

Я получаю Context Disconnected ошибки при тестировании службы ServiceStack. Я предполагаю, что это связано с отсутствием условий гонки между GC для потока обратного вызова ответа COM-объекта, моих объектов ServiceStack Service и собственной сборки мусора COM-сервера.ServiceStack + сторонняя сторона COM Inteop + исключение контекста

Edit: Это, скорее всего, та же самая проблема объясняется здесь: Avoiding disconnected context warning when shutting down a thread on which STA COM objects have been created - который рекомендует мне реализовать «некоторые ссылки подсчета, чтобы рабочий поток живы, пока все это не объекты COM определенно были выпущены» (вариант # 1 - повторно писать COM-объекты для поддержки потоковую модель MTA не представляется возможным, учитывая, что COM-объекты из 3-сторонней библиотеки)

Edit (2): Разумное использование Marshal.ReleaseComObject(obj) в методе обратного вызова. устранил проблему. Удачно, что объекты COM, о которых идет речь, были четко идентифицируемыми и в ограниченном количестве.

1. Как я могу предотвратить исключения отключенных контекстов?
2. Каков жизненный цикл сервисного объекта ServiceStack в отношении потоков и времени жизни?

Нижеприведенный тест. Однако, если запрос требует много времени для возврата (для значений «длительное время»> 30 секунд), я получаю отключенную контекстную ошибку после завершения теста, в половине случаев.


    [TestFixtureSetUp] 
    public void OnTestFixtureSetUp() 
    { 
     // TODO: remove default login credentials from code 
     // Instantiate singleton wrapper to COM object 
     var appSettings = new AppSettings(); 
     var config = appSettings.Get("3rdPartyLogin", new Config { UserName = "debug_username", Password = "debug_password" }); 
     COMServer.SetUser(config.UserName,config.Password); 

     appHost.Init(); 
     appHost.Start(ListeningOn); 
    } 

    [TestFixtureTearDown] 
    public void OnTestFixtureTearDown() 
    { 
     appHost.Dispose(); 
    } 

    [Test] 
    public void TestDataList() 
    { 
     JsonServiceClient client = new JsonServiceClient(BaseUri); 
     client.ReadWriteTimeout = new TimeSpan(0, 10, 0); // 5 minutes to timeout 
     DataList response = client.Get(new DataList()); 
     Assert.Contains("Expected Item", response.data); 
    } 

Служба ServiceStack передает экземпляр класса запросов на COM-сервер. Класс реализует метод обратного вызова для обработки ответа. Служба ServiceStack создает AutoResetEvent, передает его в объект запроса сторонней службы и вызывает WaitOne(), чтобы дождаться данных ответа. Метод обратного вызова выполняется асинхронно в новом потоке и вызывает Set() для уведомления службы ServiceStack, что данные были обработаны. (Обработка ошибок аналогична - код опущен для ясности.) Вот упрощенная служба ServiceStack и класс DataClient COM-объекта с требуемым методом обратного вызова.

public class DataListService : Service 
{ 
    public DataList Get(DataList request) 
    { 
     ComDataClient c = new ComDataClient(); 
     try 
     { 
      ComDataService data = COMServer.getDataService(); 
      if (data != null) 
      { 
       AutoResetEvent requestEvent = new AutoResetEvent(false); 
       c.requestEvent = requestEvent; 
       data.setClient(c); 

       data.getData(ComObjClass.enumDataId); 
       requestEvent.WaitOne(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Error Connecting to Data Service: " + ex.Message); 
     } 
     return c.responseData; 
    } 
} 

И класс запроса объекта COM, иллюстрирующий обратный вызов.

class ComDataClient : IDataClient 
{ 
    public DataList responseData { get; set; } 
    public AutoResetEvent requestEvent { get; set; } 

    public void acceptData(ref KeyValue[] names, ComObjClass.Content enumDataId) 
    { 
     responseData = new DataList(); 
     responseData.data = new List<String>(); 

     foreach (KeyValue name in names) 
     { 
      responseData.data.Add(name.key_); 
     } 

     // Signal the application thread 
     requestEvent.Set(); 
    } 
} 

ответ

1

Пожалуйста, смотрите Concurrency Model вики для получения дополнительной информации о модели параллельности в Servicestack.

По существу в ASP.NET новые потоки явно не созданы ServiceStack, т. Е. Запрос обрабатывается тем же потоком HTTP Worker IIS/ASP.NET.

В собственном хосте HttpListener по умолчанию AppHostHttpListenerBase также использует тот же самый поток обратного вызова IO, в AppHostHttpListenerLongRunningBase App Host, который он выполняет в потоке пула потоков. Вот недавняя статья researching the the optimal thread strategy различных самостоятельных хостинговых реализаций HttpListener.

+0

По умолчанию AppHostHttpListenerBase, который я использую, использует синхронный HttpListener, так что есть только один поток. Это предполагает модель потока STA, однако, исследуя System.Threading.ApartmentState внутри службы ServiceStack, показывает, что модель потока является, тем не менее, MTA. Итак, моя проблема точно так же, как и предполагалось, проблема перекрестной резьбы MTA/STA. –

Смежные вопросы