2010-02-05 9 views
15

के बीच डेटा साझा करना मेरे पास एक प्रक्रिया है जिसमें एकाधिक ऐपडोमेन हो सकते हैं। प्रत्येक ऐपडोमेन कुछ आंकड़े एकत्र करता है। निर्दिष्ट समय के बाद, मैं इन आंकड़ों को जमा करना चाहता हूं और उन्हें एक फ़ाइल में सहेजना चाहता हूं।AppDomains

ऐसा करने का एक तरीका रिमोटिंग है, जिसे मैं टालना चाहता हूं।

मेरे पास एकमात्र अन्य तकनीक है जो प्रत्येक ऐपडोमेन के डेटा को फ़ाइल में सहेजना है, और एक विशिष्ट समय के बाद, ऐपडोमेन में से प्रत्येक डेटा एकत्र करता है और उन्हें जमा करता है।

लेकिन यह आदर्श होगा अगर यह सब-मेमोरी में किया जा सकता है, बिना ऐपडोमेन्स के बीच की जानकारी को क्रमबद्ध करने की लागत के। क्या किसी के भी पास कोई सुझाव है?

उत्तर

12

सीरियलाइजेशन से बचने का एकमात्र तरीका मार्शलबीरफॉब्जेक्ट से प्राप्त वस्तुओं का उपयोग करके अपने डेटा का प्रतिनिधित्व करना है, लेकिन उस स्थिति में आपको अभी भी ऐपडोमेन सीमाओं में मार्शलिंग की लागत होगी। इसमें आपके अधिकांश कोड का रिफैक्टरिंग/पुनः लिखना भी शामिल हो सकता है।

संदर्भ द्वारा marshalling मानना ​​एक विकल्प नहीं है, आपको किसी बिंदु पर serialise करना होगा। यह केवल टाला नहीं जा सकता है। ऐसा करने का एक तरीका है क्योंकि नील बार्नवेल एक डेटाबेस के साथ सुझाव देता है, दूसरा एक स्थानीय फाइल के साथ होगा जैसा कि आप स्वयं को सुझाव देते हैं।

आपकी डिलीवरी टाइमलाइन और/या .NET 4.0 गोद लेने के आधार पर एक और तरीका संभव है जो मेमोरी मैप किए गए फ़ाइल का उपयोग करना होगा, .Net Framework 4.0: Using memory mapped files देखें।

+0

मैंने अभी तक कोड नहीं लिखा है। बस डिजाइन पर काम कर रहे हैं। क्या आप मुझे किसी भी लेख के बारे में बता सकते हैं जो आपके द्वारा पोस्ट किए गए पहले दृष्टिकोण का उपयोग करके डेटा साझा करने की व्याख्या करता है? – ata

+0

संदर्भ द्वारा मार्शलिंग डेटा को क्रमबद्ध करेगा, लेकिन छोटे टुकड़ों में भी। प्रत्येक विधि कॉल कुछ जानकारी को प्रभावी ढंग से डेटा का क्रमबद्ध करने के लिए कुछ जानकारी वापस कर देगा। यदि आपको डेटा के केवल एक छोटे हिस्से की आवश्यकता होती है तो यह शायद एक अच्छा विचार है। लेकिन अगर आपको पूरे डेटा को लगभग (लगभग) संसाधित करना है, तो इसे कई क्रॉस डोमेन कॉल के साथ थोड़ा सा प्राप्त करना एक बार में डेटा को क्रमबद्ध करने और स्थानांतरित करने की तुलना में अविश्वसनीय धीमा होगा। –

+2

यदि आप इस सड़क का अनुसरण करते हैं, तो InitializeLifetimeService विधि को ओवरराइड करना न भूलें; जो कुछ दिनों पहले मुझे पागल कर रहा था ("ऑब्जेक्ट" ... को डिस्कनेक्ट किया गया है या सर्वर पर मौजूद नहीं है। ") –

3

मुझे सराहना है कि आप इन मेमोरी को रखना चाहते हैं, लेकिन मेरा पहला सुझाव डेटा को डेटाबेस और क्वेरी से लिखना होगा। रिमोटिंग अभी भी एक दूरस्थ कॉल है, जहां डेटाबेस सर्वर का उपयोग करने की "लागत" में से अधिकांश आता है, और आपको यह सुनिश्चित करने के लिए लेनदेन-हैंडलिंग में बनाना होगा कि आप डेटा खोना नहीं चाहते हैं। यदि आप किसी SQL सर्वर डेटाबेस को लिखते हैं तो आपके पास लेनदेन समर्थन तैयार है और आपके लिए प्रतीक्षा कर रहा है, और यह प्रश्नों के लिए तेज़-तेज़-तेज़ है।

+0

यह एक अच्छा विचार एक डेटाबेस का उपयोग करें और डेटा कायम और एक स्थापित प्रौद्योगिकी के साथ संचार समस्या को हल करने के लिए हो सकता है, मुझे नहीं लगता कि लेन-देन एक प्रमुख लाभ होगा । यदि स्रोत एप्लिकेशन डोमेन क्रैश हो जाता है, तो डेटा खो जाता है चाहे वह केवल डेटाबेस पर या मेमोरी स्ट्रीम में तार पर था। –

4

मुझे लगता है कि बस रिमोटिंग का उपयोग करें। किसी फ़ाइल में डेटा लिखना क्रमिकरण की भी आवश्यकता है। सीरियलाइजेशन आपके द्वारा उपयोग की जाने वाली तकनीक के लगभग अपरिहार्य प्रतीत होता है। आपको कुछ चैनल का उपयोग करके एक एप्लिकेशन डोमेन से दूसरे डेटा में स्थानांतरित करना होगा और चैनल के माध्यम से इसे प्राप्त करने के लिए आपको डेटा को क्रमबद्ध करना होगा।

सीरियलाइजेशन से बचने का एकमात्र तरीका साझा स्मृति का उपयोग करना प्रतीत होता है ताकि दोनों एप्लिकेशन डोमेन बिना किसी चैनल के डेटा तक पहुंच सकें। यहां तक ​​कि एक एप्लिकेशन डोमेन की मेमोरी से दूसरे की मेमोरी में डेटा को गहरा क्लोन करना इसके मूल पर कुछ भी नहीं है, फिर बाइनरी सीरियलाइजेशन (जहां परिणाम लगातार मेमोरी स्थानों में संग्रहीत नहीं होता है)।

+0

रिमोटिंग में प्रतिबिंब भी शामिल है। वह सीरियलाइजेशन + प्रतिबिंब है। दूसरी ओर मेरा डेटा केवल कुछ लंबा और डबल मान है जिसे मैं बिना किसी ओवरहेड के फ़ाइल में लिख सकता हूं। – ata

+6

आप गलत स्पॉट देख रहे हैं। फ़ाइल का उपयोग करने की बाधा डिस्क एक्सेस है और इसमें कई मिलीसेकंड और स्थानांतरण दर आपको एक सौ मेगाबाइट प्रति सेकेंड से नीचे स्थानांतरित करने देगी। मुझे यकीन नहीं है कि रिमोटिंग की वास्तविक बाधा क्या है (जहां तक ​​मुझे याद है कि प्रदर्शन क्रॉस डोमेन कॉल की संख्या से सीमित है, ट्रांसफर डेटा की मात्रा नहीं है) लेकिन एप्लिकेशन डोमेन के बीच प्रति सेकंड कई सौ मेगाबाइट स्थानांतरित करना संभव है । फास्ट पथ का उपयोग कर स्ट्रिंग रीमिंग प्रति सेकंड कई गीगाबाइट की स्थानांतरण दर प्राप्त करता है। –

20

मार्शलिंग की लागत के बिना ऐपडोमेन्स के बीच डेटा साझा करना संभव है। लेकिन यह एक बदसूरत तरीका है। आप एक स्रोत डेटा ऑब्जेक्ट बना सकते हैं जिसे सभी ऐपडोमेन के बीच संदर्भ द्वारा साझा किया जाता है। मार्शलिंग की लागत के बिना इस तरह आप एक साझा ऑब्जेक्ट में सभी डेटा प्राप्त करते हैं। सच होने के लिए बहुत आसान लगता है?

पहली बात यह जानना है कि मार्शलिंग के बिना ऐपडोमेन्स के बीच डेटा कैसे साझा करें। इसके लिए आपको मार्शल.UnsafeAddrOfPinnedArrayElement के माध्यम से अपने डेटा स्रोत ऑब्जेक्ट का ऑब्जेक्ट पता मिलता है। फिर आप इस IntPtr को सभी AppDomains में पास करते हैं, जिनमें रुचि रखते हैं। लक्ष्य ऐपडोमेन में आपको इस इंट्राट्र को वापस ऑब्जेक्ट संदर्भ में डालने की आवश्यकता है जिसे JIT :: CastAny किया जा सकता है जो किया जाता है यदि आप किसी ऑब्जेक्ट को किसी विधि से वापस करते हैं और उसके पॉइंटर को स्टैक पर दबाते हैं।

व्हायोला आपने ऐपडोमेन्स के बीच सादा सूचक के रूप में एक वस्तु साझा की है और आपको अमान्यकास्ट अपवाद प्राप्त हैं। समस्या यह है कि आपको अपने सभी ऐपडोमेन लोडर ऑप्टिमाइज़ेशन के लिए सेट करना होगा।मल्टीडोमेन यह सुनिश्चित करने के लिए कि साझा डेटा प्रकार को परिभाषित करने वाली असेंबली को AppDomain तटस्थ प्रकार के रूप में लोड किया गया है जिसमें सभी ऐपडोमेन के बीच एक ही विधि तालिका सूचक है।

आप एक उदाहरण एप्लिकेशन पा सकते हैं जो वास्तव में WMemoryProfiler के हिस्से के रूप में करता है। नमूना कोड में detailed explanation and download link के लिए यह लिंक देखें।

बुनियादी कोड

[LoaderOptimization(LoaderOptimization.MultiDomain)] 
static public void Main(string[] args) 
{ 

    // To load our assembly appdomain neutral we need to use MultiDomain on our hosting and child domain 
    // If not we would get different Method tables for the same types which would result in InvalidCastExceptions 
    // for the same type. 
    var other = AppDomain.CreateDomain("Test"+i.ToString(), AppDomain.CurrentDomain.Evidence, new AppDomainSetup 
     { 
      LoaderOptimization = LoaderOptimization.MultiDomain, 
     }); 

    // Create gate object in other appdomain 
    DomainGate gate = (DomainGate)other.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(DomainGate).FullName); 

    // now lets create some data 
    CrossDomainData data = new CrossDomainData(); 
    data.Input = Enumerable.Range(0, 10).ToList(); 

    // process it in other AppDomain 
    DomainGate.Send(gate, data); 

    // Display result calculated in other AppDomain 
    Console.WriteLine("Calculation in other AppDomain got: {0}", data.Aggregate); 
    } 
} 
+0

वास्तव में अच्छा जवाब। मुझे सबसे पहले संदेह था कि इस तरह के दो ऐपडोमेन के बीच एक ही ऑब्जेक्ट्स साझा करना किसी भी अनपिन किए गए ऑब्जेक्ट्स के जीसी कारण के साथ विनाश को मिटा देगा (केवल एक साझा ऑब्जेक्ट पिन किया गया है)। लेकिन जैसा कि आप अपने लेख में अच्छी तरह से रूपरेखा करते हैं, सभी ऐपडोमेन्स में केवल एक जीसी है, इसलिए यह काम करता है। सुन्दर सामान! – nitrogenycs

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