我被一个架构不佳的解决方案所困扰.它不是线程安全的!
我在解决方案中有几个共享类和成员,在开发期间一切都很酷……
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);
- }
- }