[英]How do I implement thread affinity in C#?
我有一个需要线程关联的第三方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仍在池中的任何线程上执行。 我究竟做错了什么?
任何帮助将不胜感激。 非常感谢你。
默认的同步上下文在线程池上执行您的工作(因此,您没有线程亲缘关系)。
如果要确保将工作始终发布到同一线程,则需要编写自己的同步上下文。 例如:
public class SingleThreadSynchronizationContext : SynchronizationContext
{
private readonly BlockingCollection<(SendOrPostCallback callback, object state)> _queue;
private readonly Thread _processingThread;
public SingleThreadSynchronizationContext()
{
_queue = new BlockingCollection<(SendOrPostCallback, object)>();
_processingThread = new Thread(Process) { IsBackground = true };
_processingThread.Start();
}
public override void Send(SendOrPostCallback d, object state)
{
using (var mutex = new ManualResetEventSlim())
{
var callback = new SendOrPostCallback(s =>
{
d(s);
mutex.Set();
});
_queue.Add((callback, state));
mutex.Wait();
}
}
public override void Post(SendOrPostCallback d, object state)
{
_queue.Add((d, state));
}
public override SynchronizationContext CreateCopy()
{
return this;
}
private void Process()
{
SetSynchronizationContext(this);
foreach (var item in _queue.GetConsumingEnumerable())
{
item.callback(item.state);
}
}
}
请注意,此同步上下文假定回调中未捕获的异常将使进程崩溃。 如果不是这种情况(例如,因为您有一个全局异常处理程序),则应该添加一些错误处理(在Process
和Send
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.