Wie ein AppDomain verwenden, um eine statische Klasse Spielraum für Thread-sichere Verwendung zu begrenzen?

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

Frage

Ich habe von einer schlecht architected Lösung gebissen. Es ist nicht Thread-sicher!

Ich habe mehr gemeinsam genutzte Klassen und Mitglieder in der Lösung und während der Entwicklung war alles cool ...
BizTalk hat mein Schlachtschiff versenkt.

Wir verwenden eine benutzerdefinierte BizTalk Adapter meine Baugruppen zu nennen. Der Adapter ist mein Code aufrufen und Dinge parallel laufen, so dass ich davon ausgehen, es mehrere Threads alle unter dem gleichen AppDomain verwendet.

Was würde Ich mag zu tun ist mein Code unter seinem eigenen AppDomain laufen lassen, so dass die gemeinsamen Probleme, die ich nicht miteinander Dreck haben.

Ich habe eine sehr einfache Klasse, die das BizTalk Adapter dann Instanziieren einen Prozess () -Methode ausgeführt wird.

Ich möchte eine neue AppDomain in meinem Process () Methode erstellen, so dass jedes Mal BizTalk anderen Thread dreht, wird er seine eigene Version der statischen Klassen und Methoden.

BizTalkAdapter Code:

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

    }

Dies ist die Klasse BizTalk Anrufe:

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

    }

}

Zur Info: Die Loader-Klasse ist in einem separaten DLL aus der Datendatei Klasse

.

Jede Hilfe wäre sehr geschätzt. Ich werde auch weiterhin daran, den Code Thread-sicher zu arbeiten, aber ich fühle mich wie dies die „einfache“ Antwort sein könnte.

Wenn jemand einen anderen Gedanken hat, bitte in werfen.

Danke,
Keith

  

Nur der Vollständigkeit halber.

     

Ich fand, dass, wenn ich markiere den Sendeadapter als „Ordered Delivery“ in   die „Transport Erweiterte Optionen“ -Dialog konnte ich das vermeiden,   Multi-Thread-Probleme ich habe.

     

Ich stelle dar, dies eine weitere mögliche Antwort auf mein Problem ist, aber nicht   zwangsläufig auf die Frage.

War es hilfreich?

Lösung

Mit App Domains, die Sie so etwas tun könnte:

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

Andere Tipps

Welche Bit genau ist ein Schmerz im Hinblick auf die Thread-Sicherheit zu sein? Ich kann keine statischen Zustand noch Singletons sehen - und es scheint angemessen, „neue“ Objekte zu sein ... bin ich blind

Also, was ist das Symptom Sie sehen ...

Eine AppDomain Antwort wird (relativ) langsam. Im Rahmen einer Middleware gestütztes System dies in Ordnung sein könnte (das heißt, die „relativ“ ist in der gleichen Ball-Park).

Wenn Sie tun hat einigen statischen Zustand irgendwo, eine andere Option, die manchmal funktioniert, ist [Threadstatic] -, die die Laufzeit interpretiert als „das statische Feld pro Thread einzigartig ist“. Sie müssen sich mit der Initialisierung, vorsichtig sein, obwohl -. Der statische Konstruktor auf Thread A könnte ein Feld zuweisen, aber dann B Thread sehen würde ein Null / 0 / etc

Warum nicht nur eine Sperre setzen um den Code, den Sie der Reihe nach ausgeführt werden soll? Es wird ein Engpass sein, aber es sollte in einer Multithread-Umgebung arbeiten.

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

    }

}

Wenn Sie Statik geteilt haben, die miteinander in Konflikt stehen, dann möchten Sie vielleicht versuchen Sie [Threadstatic] Attribut zu ihnen. Dadurch wird sie zu jedem Thread lokal machen. Das kann Ihr Problem in kurzer Zeit lösen. Eine richtige Lösung wäre, einfach Ihre Sachen rearchitect Thread-sicher zu sein.

Nur der Vollständigkeit halber.

Ich fand, dass, wenn ich den Sendeadapter als „Ordered Delivery“ markiert in den „Transport Erweiterte Optionen“ -Dialog konnte ich die Multi-Thread-Probleme vermeiden, die ich hatte.

Ich stelle dar, dies eine weitere mögliche Antwort auf mein Problem ist, aber nicht unbedingt auf die Frage.

Erstellen und eine Appdomain für jeden Anruf abzureißen - ich nehme es sind Sie über die Leistung auf diesen einen nicht besorgt

?

Im Idealfall sollten Sie den genannten Code ändern THREAD sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top