2009-04-09 6 views
5

Zunächst möchte ich, dass der kontextbasierte Speicher im gesamten Framework konsistent ist!Ich suche einen kontextbasierten Speicher für alle Größen

Mit diesem gesagt, ich suche nach einer eleganten Lösung, um diese Eigenschaften über ASP.NET, WCF und anderen multithreaded .NET-Code sicher zu machen. Die Eigenschaften befinden sich in einigen Tracehelfern auf niedriger Ebene (diese werden über Methoden verfügbar gemacht, wenn Sie sich fragen, warum sie intern sind).

Ich würde lieber nicht von nicht benötigten Baugruppen (wie System.Web, etc) abhängig sein. Ich möchte nicht verlangen, dass irgendjemand diesen Code verwendet, um irgendetwas zu konfigurieren. Ich will nur, dass es funktioniert;) Das kann aber zu groß für eine Bestellung sein ...

Jeder hat irgendwelche Tricks im Ärmel?

internal static string CurrentInstance 
    { 
     get 
     { 
      return CallContext.LogicalGetData(currentInstanceSlotName) as string; 
     } 
     set 
     { 
      CallContext.LogicalSetData(currentInstanceSlotName, value); 
     } 
    } 

    internal static Stack<ActivityState> AmbientActivityId 
    { 
     get 
     { 
      Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>; 
      if (stack == null) 
      { 
       stack = new Stack<ActivityState>(); 
       CallContext.LogicalSetData(ambientActivityStateSlotName, stack); 
      } 

      return stack; 
     } 
    } 
(Ich habe Spring Implementierung gesehen)

aktualisieren

Durch sichere ich nicht synchronisiert bedeuten. Hintergrund zum Thema here

+0

Ich habe nicht viel zu bieten, aber ich bin auch an diesem Thema interessiert. FWIW Ich erinnere mich daran, in einem Quell-Repository (wahrscheinlich Castle, NInject oder NHibernate) verschiedene Implementierungen von etwas wie IContext zu sehen, von denen ich vermute, dass sie in einer App enthalten sind. Jede IContext-Implementierung verwendete eine andere Technologie (CallContext, HttpContext, Thread.SetData usw.). Ich weiß nicht genau, wie sie verwendet werden sollten, aber mein erster Gedanke war, dass es "Kontext" abstrahieren sollte. Wie auch immer, ich kann sehen, ob ich finde, was ich vorher gefunden habe und einen Link posten. Es könnte nützlich sein. – wageoghe

Antwort

0

Ich weiß nicht, dass die Verwendung von CallContext hier der richtige Schritt ist, wenn es nur darum geht, thread-sicheren Zugriff auf Ihre Eigenschaften bereitzustellen. Wenn dies der Fall ist, ist die Lock-Anweisung alles, was Sie brauchen.

Sie müssen jedoch sicherstellen, dass Sie es korrekt anwenden.

Mit CallContext erhalten Sie thread-sicheren Zugriff, weil Sie separate Instanzen von CallContext haben werden, wenn Anrufe in anderen Threads (oder anderen Stores) eingehen. Das unterscheidet sich jedoch sehr davon, ob der Zugriff auf eine threadsichere Ressource möglich ist.

Wenn Sie den gleichen Wert über mehrere Threads teilen möchten, dann ist die Lock-Anweisung der richtige Weg. Wenn Sie bestimmte Werte pro Thread/Aufruf verwenden möchten, verwenden Sie andernfalls CallContext oder die statischen GetData/SetData-Methoden für die Thread-Klasse oder das ThreadStatic-Attribut (oder eine beliebige Anzahl von Thread-basierten Speichermechanismen).

+0

Ich bin nicht mit der Synchronisation beschäftigt. Wie Sie schon sagten, es gibt viele Mechanismen für den kontextbasierten Speicher und einige funktionieren nicht in bestimmten Situationen (zB CallContext und ThreadStatic in ASP.NET) daher meine Frage. – jsw

2

Hier ist ein Link zu (zumindest zum Teil) NHibernate „Kontext“ Umsetzung:

https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/

Es ist mir nicht ganz klar, wo und wie diese ins Spiel kommt im Zusammenhang mit NHibernate. Das heißt, wenn ich einige Werte in "dem Kontext" speichern möchte, würde ich "den Kontext" von NHibernate bekommen und meine Werte hinzufügen? Ich benutze NHibernate nicht, also weiß ich es nicht wirklich.

Ich nehme an, dass Sie selbst schauen und bestimmen könnten, ob diese Art der Implementierung für Sie nützlich wäre. Offensichtlich wäre die Idee, die gewünschte Implementierung zu injizieren, abhängig von der Art der Anwendung (ASP.NET, WCF, etc). Das impliziert wahrscheinlich eine Konfiguration (vielleicht minimal, wenn man MEF verwenden würde, um "die" ICurrentSessionContext-Schnittstelle zu laden).

Jedenfalls fand ich diese Idee interessant, wenn ich es vor einiger Zeit gefunden, während auf CallContext.SetData/GetData/LogicalSetData/LogicalGetData der Suche nach Informationen, Thread.SetData/GetData, [ThreadStatic] usw.

Auch basierend auf der Nutzung von CallContext.LogicalSetData statt CallContext.SetData, ich Angenommen, Sie möchten die Tatsache ausnutzen, dass Informationen, die mit dem logischen Thread verknüpft sind, an untergeordnete Threads weitergegeben werden, anstatt nur einen "thread-sicheren" Ort zum Speichern von Informationen zu haben.Wenn Sie die AmbientActivity beim Start Ihrer App festlegen (pr Push) und dann keine weiteren Aktivitäten mehr ausführen, sind alle nachfolgenden Threads ebenfalls Teil derselben Aktivität, da die über LogicalSetData gespeicherten Daten von untergeordneten Threads geerbt werden.

Wenn Sie in der Zwischenzeit etwas gelernt haben, seit Sie diese Frage zum ersten Mal gestellt haben, wäre ich sehr daran interessiert, davon zu hören. Selbst wenn Sie dies nicht tun würden, wäre ich daran interessiert zu erfahren, was Sie mit dem Kontext tun.

Im Moment arbeite ich an der Pflege einiger Kontextinformationen für die Protokollierung/Ablaufverfolgung (ähnlich der Trace.CorrelationManager.ActivityId- und der Trace.CorrelationManager.LogicalOpertionStack- und log4net/NLog-Kontextunterstützung). Ich möchte einige Kontext (aktuelle App, aktuelle App-Instanz, aktuelle Aktivität (möglicherweise geschachtelt)) für die Verwendung in einer App oder WCF-Dienst UND ich möchte es "automatisch" über WCF-Dienstgrenzen zu verbreiten. Dies ermöglicht es, Protokollierungsanweisungen, die in einem zentralen Repository protokolliert werden, nach Client/Aktivität/etc zu korrelieren. Wir wären in der Lage, alle Logging-Anweisungen für eine bestimmte Instanz einer bestimmten Anwendung abzufragen und zu korrelieren. Die Protokollierungsanweisungen könnten auf dem Client oder in einem oder mehreren WCF-Diensten generiert worden sein.

Die WCF-Propagierung von ActivityId ist für uns nicht unbedingt ausreichend, weil wir mehr als nur die ActivityId propagieren wollen (oder wir denken, dass wir es tun). Außerdem möchten wir diese Informationen von Silverlight-Clients an WCF-Dienste weitergeben und Trace.CorrelationManager ist in Silverlight nicht verfügbar (zumindest nicht in 4.0, vielleicht wird es in Zukunft so sein).

Momentan prototypiere ich die Verbreitung unserer "Kontext" -Informationen mit IClientMessageInspector und IDispatchMessageInspector. Es sieht so aus, als würde es wahrscheinlich für uns in Ordnung sein.

In Bezug auf eine Abhängigkeit von System.Web verfügt die NHibernate-Implementierung über einen "ReflectiveHttpContext", der Reflektion verwendet, um auf den HttpContext zuzugreifen, sodass keine Projektabhängigkeit von System.Web besteht. Natürlich müsste System.Web verfügbar sein, wo die App bereitgestellt wird, wenn HttpContext für die Verwendung konfiguriert ist.