我在测试ServiceStack服务时遇到了Context Disconnected错误。我假设这是由于GC对象的响应回调线程,我的ServiceStack服务的对象和COM服务器自己的垃圾收集之间的竞争条件失败。
编辑:这很可能是这里解释的同一问题:Avoiding disconnected context warning when shutting down a thread on which STA COM objects have been created - 它建议我实现“一些引用计数以保持工作线程活着,直到它的所有COM对象都有已发布“(选项#1 - 重新编写COM对象以支持MTA线程模型是不可能的,因为COM对象来自第三方库。)
编辑(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服务和COM对象的DataClient类,以及必需的回调方法。
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();
}
}
答案 0 :(得分:1)
有关Concurrency Model中并发模型的更多信息,请参阅Servicestack wiki。
基本上在ASP.NET中,ServiceStack没有显式创建新线程,即请求由同一个IIS / ASP.NET HTTP Worker线程处理。
在自托管的HttpListener主机中,默认的AppHostHttpListenerBase也在它在线程池线程上执行的AppHostHttpListenerLongRunningBase App Host中使用相同的IO回调线程。这是最近发布的researching the the optimal thread strategy个不同的自托管HttpListener主机实现。