WCF后续之旅(11) 关于并发、回调的线程关联性(Thread Affinity)2011-01-03 cnblogs artech对于一般的多线程操作,比如异步地进行基于文件系统的IO操作;异步地调用Web Service;或者是异步地进行数据库访问等等,是和具体的线程无关的。也就是说,对于这些操作,任意创建一个新的线程来执行都是等效的。但是有些情况下,有些操作却只能在固定的线程下执行。比如,在GUI应用下,对控件的访问就需要在创建该控件的线程下执行;或者我们在某个固定的线程中通过TLS(Thread Local Storage)设置了一些Context信息,供具体的操作使用,我们把操作和某个固定的线程的依赖称为线程关联性(Thread Affinity)。在这种情况下,我们的异步操作就需要被Marshal到固定的线程执行。在WCF并发或者Callback的情况下也具有这样的基于线程关联性的问题。一、从基于Windows Application客户端的WCF回调失败谈起在"我的WCF之旅"系列文章中,有一篇(WinForm Application中调用Duplex Service出现TimeoutException的原因和解决方案)专门介绍在一个Windows Application客户端应用, 通过WCF 的Duplex通信方式进行回调失败的文章.我们今天以此作为出发点介绍WCF在Thread Affinity下的表现和解决方案.我们来创建一个WCF的应用来模拟该场景: 客户端是一个基于Windows Form应用, 完成一个计算器的功能, 用户输入操作数,点击"计算"按钮, 后台通过调用WCF service, 并传递一个用于显示计算结果的Callback对象; service进行相应的计算得到最后的运算结果,调用该Callback对象将运算结果显示到客户端界面.这是我们的WCF四层结构:

1、Contract:ICalculate & ICalculateCallback
namespace Artech.ThreadAffinity.Contracts
{
[ServiceContract(CallbackContract = typeof(ICalculateCallback))]
public interface ICalculate
{
[OperationContract]
void Add(double op1, double op2);
}
}
这是Service Contract,下面是Callback Contract,用于显示运算结果:
namespace Artech.ThreadAffinity.Contracts
{
public interface ICalculateCallback
{
[OperationContract]
void DisplayResult(double result);
}
}