【发布时间】:2017-12-14 22:09:33
【问题描述】:
我有一个需要线程关联的第三方 API。我在我的服务应用程序中使用 WCF 来处理来自客户端的请求,然后将这些请求委托给这个 API。由于 WCF 使用线程池来处理请求,因此我尝试使用以下代码解决此问题(使用 SynchronizationContext 类):
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;
namespace MyAPIService
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService: IService
{
ThirdPartyAPI m_api;
SynchronizationContext m_context;
MyService()
{
m_api = new ThirdPartyAPI();
}
public bool Connect(string ipaddress, int port)
{
m_context = (SynchronizationContext.Current == null) ? new SynchronizationContext() : SynchronizationContext.Current;
return m_api.Connect(ipaddress, port);
}
public bool Disconnect()
{
throw new NotImplementedException();
}
public bool IsConnected()
{
return Send(() => m_api.IsConnected());
}
public TResult Send<TResult>(Func<TResult> func)
{
TResult retval = default(TResult);
m_context.Send(new SendOrPostCallback((x) =>
{
retval = func();
})
, null);
return retval;
}
}
}
}
我认为这将允许我在调用 Connect 的同一线程上执行 IsConnected 方法,但从测试来看并非如此。 IsConnected 仍然在池中的任何线程上执行。我做错了什么?
任何帮助将不胜感激。 非常感谢。
【问题讨论】:
-
您还需要客户端部分的minimal reproducible example,并确保调试代码以了解您获取 MyService 的新实例是否比您预期的更频繁,或者您的同步上下文管理不起作用。
-
虽然 SynchronizationContext 是适合这项工作的工具,但它也不是魔法。如果您创建一个新的默认同步上下文 (
new SynchronizationContext()),它会将工作发布到线程池(这不是您想要的)。您的外部 API(我想它是一个 COM 对象)是否有某种回调方法?如果是这样,则可以在该回调中捕获同步上下文,然后在其他地方重用它。否则,恐怕你得自己写了 -
@KevinGosse 第三方 API 实际上不是 com 对象。当您说“自己编写”时,您是指我自己的同步上下文吗?
-
@markf78 是的。编写同步上下文来管理单个线程应该不会太困难。事实上,这里和那里可能有一些可用的实现
标签: c# multithreading wcf synchronizationcontext