스레드 안전 사용을위한 정적 클래스의 범위를 제한하기 위해 AppDomain을 사용하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/307292

문제

나는 제대로 건축되지 않은 솔루션에 물렸다. 스레드 안전하지 않습니다!

솔루션에 몇 가지 공유 클래스와 회원이 있으며 개발 중에 모든 것이 시원했습니다 ...
Biztalk는 내 전투선을 가라 앉았습니다.

우리는 내 어셈블리를 호출하기 위해 맞춤형 biztalk 어댑터를 사용하고 있습니다. 어댑터는 내 코드를 호출하고 병렬로 실행 중이므로 동일한 appDomain에서 여러 스레드를 사용하고 있다고 가정합니다.

내가하고 싶은 것은 내 코드를 자체 appdomain에서 실행하여 공유 된 문제가 서로 뭉개지 않을 것입니다.

Biztalk 어댑터가 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);

    }

이것은 클래스 비즈 토크 호출입니다.

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...

    }

}

참고 : 로더 클래스는 DataFile 클래스에서 별도의 DLL에 있습니다.

모든 도움이 감사하겠습니다. 나는 코드 스레드-안전을 위해 계속 노력할 것이지만, 이것이 "간단한"대답 일 수 있다고 생각합니다.

누군가 다른 생각이 있으면 던져주세요.

고맙습니다,
키이스

완전성을 위해.

"Transport Advanced Options"대화 상자에서 Send 어댑터를 "주문 배달"으로 표시하면 내가 가진 멀티 스레드 문제를 피할 수 있다는 것을 알았습니다.

나는 이것이 내 문제에 대한 또 다른 가능한 대답이라고 생각하지만 반드시 질문에 대한 것은 아닙니다.

도움이 되었습니까?

해결책

앱 도메인을 사용하면 다음과 같은 작업을 수행 할 수 있습니다.

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);       
    }
}

다른 팁

스레드 안전 측면에서 정확히 어느 비트가 고통인지는 무엇입니까? 나는 정적 상태 나 싱글 톤을 볼 수 없으며, 적절한 "새로운"대상이있는 것 같습니다 ... 나는 눈이 멀었습니까?

그래서 당신이보고있는 증상은 무엇입니까 ...

AppDomain 답변은 (상대적으로) 느립니다. 미들웨어 지원 시스템의 일부로 이것은 괜찮을 수 있습니다 (즉, "상대적으로"는 같은 볼 파크에 있습니다).

만약 너라면 하다 어딘가에 정적 상태가 있는데, 때로는 작동하는 또 다른 옵션은 [Threadstatic]입니다. 런타임은 "이 정적 필드가 스레드 당 고유 한"것으로 해석합니다. 그러나 초기화에주의를 기울여야합니다. 스레드 A의 정적 생성자는 필드를 할당 할 수 있지만 스레드 B는 NULL/0/등을 볼 수 있습니다.

왜 순차적으로 실행하려는 코드를 잠그지 않겠습니까? 병목 현상이지만 멀티 스레드 환경에서 작동해야합니다.

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();
        }

    }

}

서로 충돌하는 정적을 공유 한 경우 [Threadstatic] 속성을 추가하려고 시도 할 수 있습니다. 이것은 각 스레드에 로컬로 만들 것입니다. 그것은 단기적으로 당신의 문제를 해결할 수 있습니다. 올바른 솔루션은 단순히 물건을 실로 삭제하기 위해 단순히 재구성하는 것입니다.

완전성을 위해.

"Transport Advanced Options"대화 상자에서 Send 어댑터를 "주문 배달"으로 표시하면 내가 가진 멀티 스레드 문제를 피할 수 있다는 것을 알았습니다.

나는 이것이 내 문제에 대한 또 다른 가능한 대답이라고 생각하지만 반드시 질문에 대한 것은 아닙니다.

각 통화마다 앱 도메인을 생성하고 찢어 버리는 것 - 나는 당신이 이것에 대한 성능에 대해 걱정하지 않습니까?

이상적으로는 호출 된 코드를 threadSafe로 변경해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top