我被一个架构不佳的解决方案所困扰.它不是线程安全的!
我在解决方案中有几个共享类和成员,在开发期间一切都很酷……
BizTalk已经沉没了我的战舰.
我们使用自定义BizTalk适配器来调用我的程序集.适配器正在调用我的代码并并行运行,所以我假设它在同一个AppDomain下使用多个线程.
我想要做的是让我的代码在自己的AppDomain下运行,这样我所拥有的共享问题就不会相互混淆.
我有一个非常简单的类,BizTalk适配器实例化然后运行Process()方法.
我想在我的Process()方法中创建一个新的AppDomain,所以每次BizTalk都旋转另一个线程时,它将拥有自己的静态类和方法版本.
BizTalkAdapter代码:
// this is inside the BizTalkAdapter and it is calling the Loader class // private void SendMessage(IBaseMessage message,TransactionalTransmitProperties properties) { Stream strm = message.BodyPart.GetOriginalDataStream(); string connectionString = properties.ConnectionString; string msgFileName = message.Context.Read("ReceivedFileName","http://schemas.microsoft.com/BizTalk/2003/file-properties") as string; Loader loader = new Loader(strm,msgFileName,connectionString); loader.Process(); EventLog.WriteEntry("Loader","Successfully processed: " + msgFileName); }
这是BizTalk调用类:
public class Loader { private string connectionString; private string fileName; private Stream stream; private DataFile dataFile; public Loader(Stream stream,string fileName,string connectionString) { this.connectionString = connectionString; this.fileName = fileName; this.stream = stream; } public void Process() { //***** Create AppDomain HERE ***** // run following code entirely under that domain dataFile = new DataFile(aredStream,fileName,connectionString); dataFile.ParseFile(); dataFile.Save(); // get rid of the AppDomain here... } }
仅供参考:Loader类位于dataFile类的单独DLL中.
任何帮助,将不胜感激.我将继续努力使代码线程安全,但我觉得这可能是“简单”的答案.
如果有人有任何其他想法,请投入.
谢谢,
基思
Just for completeness.
I did find that if I marked the send adapter as “Ordered Delivery” in
the “Transport Advanced Options” dialog I was able to avoid the
multi-thread issues I was having.I figure this is another possible answer to my problem,but not
necessarily to the question.
解决方法
使用应用域您可以执行以下操作:
public class Loader { private string connectionString; private string fileName; private Stream stream; private DataFile dataFile; public Loader(Stream stream,string connectionString) { this.connectionString = connectionString; this.fileName = fileName; this.stream = stream; } public void Process() { //***** Create AppDomain HERE ***** string threadID = Thread.CurrentThread.ManagedThreadId.ToString(); AppDomain appDomain = AppDomain.CreateDomain(threadID); DataFile dataFile = (DataFile) appDomain.CreateInstanceAndUnwrap( "<DataFile AssemblyName>","DataFile",true,BindingFlags.Default,null,new object[] { aredstream,filename,connectionString },null); dataFile.ParseFile(); dataFile.Save(); appDomain.Unload(threadID); } }