基于自定义Unity生存期模型PerCallContextLifeTimeManager的问题
perthreadlifetimemanager的问题
使用unity内置的perthreadlifetimemanager生存期模型时,其基于threadstatic的tls(thread local storage)设计,也就是说对于每个托管的managedthreadid,其会缓存已生成的对象实例。
由于clr维护了托管线程池,使用过的线程并不会立即销毁,在需要的时候会继续复用。在类似asp.net percall或wcf percall条件下,当call1在线程managedthreadid1中处理完毕后,call2发生,而call2很有可能也在线程managedthreadid1中处理。这种条件下call2会自动复用处理call1时生成并缓存的对象实例。
如果我们希望每次调用(percall)都生成专用的对象实例,则perthreadlifetimemanager在此种场景下不适合。
解决办法有两种:
1.继续使用perthreadlifetimemanager模型,不适用threadpool,而手动创建和销毁线程。
2.自定义对象生存期模型
percallcontextlifetimemanager
public class percallcontextlifetimemanager : lifetimemanager
{
private string _key =
string.format(cultureinfo.invariantculture,
"percallcontextlifetimemanager_{0}", guid.newguid());
public override object getvalue()
{
return callcontext.getdata(_key);
}
public override void setvalue(object newvalue)
{
callcontext.setdata(_key, newvalue);
}
public override void removevalue()
{
callcontext.freenameddataslot(_key);
}
}
使用举例
private static void testpercallcontextlifetimemanager()
{
iexample example;
using (iunitycontainer container = new unitycontainer())
{
container.registertype(typeof(iexample), typeof(example),
new percallcontextlifetimemanager());
container.resolve<iexample>().sayhello();
container.resolve<iexample>().sayhello();
action<int> action = delegate(int sleep)
{
container.resolve<iexample>().sayhello();
thread.sleep(sleep);
container.resolve<iexample>().sayhello();
};
thread thread1 = new thread((a) => action.invoke((int)a));
thread thread2 = new thread((a) => action.invoke((int)a));
thread1.start(50);
thread2.start(55);
thread1.join();
thread2.join();
threadpool.queueuserworkitem((a) => action.invoke((int)a), 50);
threadpool.queueuserworkitem((a) => action.invoke((int)a), 55);
thread.sleep(100);
threadpool.queueuserworkitem((a) => action.invoke((int)a), 50);
threadpool.queueuserworkitem((a) => action.invoke((int)a), 55);
thread.sleep(100);
threadpool.queueuserworkitem((a) => action.invoke((int)a), 50);
threadpool.queueuserworkitem((a) => action.invoke((int)a), 55);
thread.sleep(100);
example = container.resolve<iexample>();
}
example.sayhello();
console.readkey();
}