首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用AppDomain来限制静态类的作用域以实现线程安全使用?

如何使用AppDomain来限制静态类的作用域以实现线程安全使用?
EN

Stack Overflow用户
提问于 2008-11-20 23:34:59
回答 6查看 3.9K关注 0票数 7

我被一个架构不好的解决方案咬了一口。这不是线安全!

我在解决方案中有几个共享类和成员,在开发过程中一切都很酷.

BizTalk击沉了我的战舰。

我们使用自定义的BizTalk适配器来调用我的程序集。适配器调用我的代码并并行运行,因此我假设它使用的都是同一个AppDomain下的多个线程。

我想要做的是让我的代码在它自己的AppDomain下运行,这样我拥有的共享问题就不会相互干扰。

我有一个非常简单的类,BizTalk适配器正在实例化,然后运行一个Process()方法。

我希望在Process()方法中创建一个新的AppDomain,因此每次BizTalk旋转另一个线程时,它都会有自己版本的静态类和方法。

BizTalkAdapter代码:

代码语言:javascript
复制
  // 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调用:

代码语言:javascript
复制
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...

    }

}

FYI: Loader类与dataFile类处于分离的DLL中。

任何帮助都将不胜感激。我将继续努力使代码线程安全,但我觉得这可能是“简单”的答案。

如果有人有其他想法,请加入。

谢谢,

基思

只是为了完整性。

我确实发现,如果我在“”对话框中将发送适配器标记为“有序传递”,我就能够避免出现多线程问题。

我认为这是解决我的问题的另一个可能的答案,但不一定是对这个问题的回答。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2008-11-21 04:15:03

使用应用程序域,您可以这样做:

代码语言:javascript
复制
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 *****
        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,
                        null,
                        null);
        dataFile.ParseFile();
        dataFile.Save();

        appDomain.Unload(threadID);       
    }
}
票数 3
EN

Stack Overflow用户

发布于 2008-11-21 05:28:11

确切地说,哪一点在线程安全方面是一个痛苦?我看不到任何静态或单一的状态-似乎有合适的“新”对象.我瞎了吗?

你看到的症状是什么..。

AppDomain的回答将是(相对)慢的。作为中间件支持的系统的一部分,这可能是可以的(例如,“相对”在同一个球场中)。

如果您确实有某种静态状态,另一个有时有效的选项是ThreadStatic --运行时将其解释为“每个线程该静态字段是唯一的”。但是,您需要小心初始化--线程A上的静态构造函数可能会分配一个字段,但是线程B会看到null/0/etc。

票数 3
EN

Stack Overflow用户

发布于 2008-11-20 23:41:44

为什么不对你想要依次执行的代码设置一个锁呢?这将是一个瓶颈,但它应该在多线程环境中工作。

代码语言:javascript
复制
public class Loader
{
    private static object SyncRoot = new object();
    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()
    {

        lock(SyncRoot) {
            dataFile = new DataFile(aredStream, fileName, connectionString);
            dataFile.ParseFile();
           dataFile.Save();
        }

    }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/307292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档