2010-11-28 16 views
28

मैं कुछ विरासत कोड को प्रबंधित करने के लिए ऐपडोमेन का उपयोग करके विचारों का प्रयोग कर रहा हूं जिसमें बहु-थ्रेडेड वातावरण में बहुत से स्थिर फ़ील्ड हैं।ऐपडोमेन में स्टेटिक फ़ील्ड

मैं जवाब इस सवाल पढ़ें: How to use an AppDomain to limit a static class' scope for thread-safe use?, सोचा था कि यह काफी आशाजनक है और विधानसभा ClassLibrary1.dll में एक बहुत ही सरल वर्ग के साथ इसे आज़माने का फैसला किया:

namespace ClassLibrary1 
{ 
    public static class Class1 
    { 
     private static int Value = 0; 

     public static void IncrementAndPrint() 
     { 
      Console.WriteLine(Value++); 
     } 
    } 
} 

और यहाँ मेरे कोड है कि assemblyinto 2 अलग लोड करता है एप्लिकेशन डोमेन और IncrementAndPrint का आह्वान() कई बार:

var appDomain1 = System.AppDomain.CreateDomain("AppDomain1"); 
var appDomain2 = System.AppDomain.CreateDomain("AppDomain2"); 

var assemblyInAppDomain1 = appDomain1.Load("ClassLibrary1"); 
var assemblyInAppDomain2 = appDomain2.Load("ClassLibrary1"); 

var class1InAppDomain1 = assemblyInAppDomain1.GetType("ClassLibrary1.Class1"); 
var class1InAppDomain2 = assemblyInAppDomain2.GetType("ClassLibrary1.Class1"); 

class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 
class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 
class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 

class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 
class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 
class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 

मैं उम्मीद कर रहा था उत्पादन होने के लिए:

0 
1 
2 
0 
1 
2 

क्योंकि स्थैतिक फ़ील्ड की एक प्रति होगी AppDomain के प्रत्येक उदाहरण के लिए स्थानीय मान। हालांकि, इसके बजाय मुझे जो मिला:

0 
1 
2 
3 
4 
5 

जो मुझे बताता है कि वे अभी भी सभी स्थिर फ़ील्ड मान की एक ही प्रति साझा कर रहे हैं। क्या कोई मुझे बता सकता है कि मैंने यहां क्या गलत किया है?

अद्यतन:

मैं एरिक के सुझाव की कोशिश की, अब मैं CreateInstanceAndUnwrap फोन() के बजाय लोड() और GetType (बुलाने की AppDomain वर्ग की विधि) के रूप में नीचे दिखाया गया है। साथ ही, मैंने एक स्थिर विधि के बजाय एक उदाहरण विधि में वृद्धि और प्रिंट को परिवर्तित कर दिया है। हालांकि, मुझे अभी भी एक ही परिणाम मिल रहा है।

var appDomain1 = System.AppDomain.CreateDomain("AppDomain1"); 
var appDomain2 = System.AppDomain.CreateDomain("AppDomain2"); 

var class1InAppDomain1 = (Class1)appDomain1.CreateInstanceAndUnwrap("ClassLibrary1", "ClassLibrary1.Class1"); 
var class1InAppDomain2 = (Class1)appDomain2.CreateInstanceAndUnwrap("ClassLibrary1", "ClassLibrary1.Class1"); 

class1InAppDomain1.IncrementAndPrint(); 
class1InAppDomain1.IncrementAndPrint(); 
class1InAppDomain1.IncrementAndPrint(); 

class1InAppDomain2.IncrementAndPrint(); 
class1InAppDomain2.IncrementAndPrint(); 
class1InAppDomain2.IncrementAndPrint(); 
+0

आप टी कॉल कर रहे हैं वह वर्तमान ऐप डोमेन में स्थिर विधि है। आपको एक इंस्टेंस विधि बनाने की आवश्यकता है जो कक्षा 1 कक्षा पर स्टेटिक विधि को कॉल करे। –

+1

हाय एरिक, यदि आपने मेरे अपडेट किए गए सोर्स कोड पर एक नज़र डाली है, तो मैंने एक एपमेंट विधि में वृद्धि और प्रिंटर() को परिवर्तित कर दिया है और संबंधित ऐप डोमेन में उदाहरण बनाने के लिए CreateInstanceAndUnWrap() का उपयोग किया है। हालांकि, मुझे अभी भी एक ही परिणाम मिल रहा है – oscarkuo

+0

मैं पूरी तरह से आपके ऐपडोमेन मॉडल पर 'MarhsalByRefObject' का उल्लेख करना भूल गया। –

उत्तर

21

ऐसा लगता है कि आप किसी अन्य ऐपडोमेन से वर्तमान ऐपडोमेन में एक प्रकार लोड कर रहे हैं। इस प्रकार स्थिर कोड को कॉल करने वाला कोड वर्तमान ऐपडोमेन से कॉल कर रहा है।

मैं किसी अन्य डोमेन में किसी ऑब्जेक्ट का उदाहरण बनाये बिना किसी अन्य डोमेन में एक स्थैतिक विधि को कॉल करने के किसी भी अन्य तरीके से अनजान हूं, और उस ऑब्जेक्ट को स्थैतिक विधि कहता हूं।

उदाहरण: समाधान 2 परियोजनाओं (ClassLibrary और एक Winforms/कंसोल एप्लिकेशन) शामिल हैं

[ClassLibrary]

using System; 

namespace MyLibrary 
{ 
    public class DomainObject : MarshalByRefObject 
    { 
     private static int _Value; 

     private static void IncrementValue() 
     { 
      DomainObject._Value++; 
     } 

     public static int Value 
     { 
      get 
      { 
       return DomainObject._Value; 
      } 
     } 

     public int GetIncrementedValue() 
     { 
      DomainObject.IncrementValue(); 
      return DomainObject.Value; 
     } 
    } 
} 

[आवेदन]

private void button1_Click(object sender, EventArgs e) 
{ 
    AppDomain domain1 = AppDomain.CreateDomain("domain1"); 
    AppDomain domain2 = AppDomain.CreateDomain("domain2"); 

    DomainObject object1 = 
     domain1.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") 
     as DomainObject; 

    DomainObject object2 = 
     domain2.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") 
     as DomainObject; 

    if (object1 != null) 
    { 
     Console.WriteLine("object 1 Value = " 
          + object1.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 1 Value = " 
          + object1.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 1 Value = " 
          + object1.GetIncrementedValue().ToString()); 
    } 
    if (object2 != null) 
    { 
     Console.WriteLine("object 2 Value = " 
          + object2.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 2 Value = " 
          + object2.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 2 Value = " 
          + object2.GetIncrementedValue().ToString()); 
    } 

    /* Unload the Domain and re-create 
    * This should reset the Static Value in the AppDomain 
    */ 
    AppDomain.Unload(domain1); 
    domain1 = AppDomain.CreateDomain("domain1"); 
    object1 = domain1.CreateInstanceAndUnwrap("MyLibrary", 
               "MyLibrary.DomainObject") 
               as DomainObject; 

    if (object1 != null) 
    { 
     Console.WriteLine("object 1 Value = " 
          + object1.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 1 Value = " 
          + object1.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 1 Value = " 
          + object1.GetIncrementedValue().ToString()); 
    } 
    if (object2 != null) 
    { 
     Console.WriteLine("object 2 Value = " 
          + object2.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 2 Value = " 
          + object2.GetIncrementedValue().ToString()); 
     Console.WriteLine("object 2 Value = " 
          + object2.GetIncrementedValue().ToString()); 
    } 
} 

जेनरेट किए गए परिणाम:

object 1 Value = 1 
object 1 Value = 2 
object 1 Value = 3 
object 2 Value = 1 
object 2 Value = 2 
object 2 Value = 3 
object 1 Value = 1 
object 1 Value = 2 
object 1 Value = 3 
object 2 Value = 4 
object 2 Value = 5 
object 2 Value = 6 
+4

चीयर्स साथी, MarhsalByRefObject चाल करता है। – oscarkuo

+1

इसके अतिरिक्त, मूल रिलीज के साथ।नेट एक कम ज्ञात बग जहां वर्तमान डोमेन है कि तब परिभाषित करने का प्रकार (एक अलग डोमेन में बनाया गया) पर गैर स्थिर पद्धतियों को बुलाया में एक स्थिर विधि क्रियान्वित गैर स्थिर कोड वर्तमान डोमेन क्रियान्वित (भले ही में परिणाम होगा नहीं थी परिभाषित प्रकार एमबीआर था)। समाधान एमबीआर के प्रकारों पर स्थिर तरीकों को कॉल नहीं करना था। उस समय हम मानते थे कि यह एमआईटी अनुकूलन के साथ एक समस्या थी जो एमबीआर पर परिभाषित एक स्थिर विधि के उपयोग के कारण एमबीआर कॉल को रेखांकित किया जा सकता था। –

संबंधित मुद्दे