2011-03-28 8 views
6

हम सिस्टम का उपयोग कर रहे हैं। ऐड-इन्स को अलग-अलग बच्चे ऐपडोमेन में लोड करने के लिए जोड़ें, और अगर इसमें एक अनचाहे अपवाद है तो हम एड-इन ऐपडोमेन को अनलोड करें।एक बच्चे से गैर-धारावाहिक अवांछित अपवादों से निपटने के लिए ऐपडोमेन

क्योंकि संस्करण 2.0 से .NET का डिफ़ॉल्ट व्यवहार पूरी प्रक्रिया को तोड़ना था, यदि किसी भी ऐपडोमेन के पास एक अनचाहे अपवाद है, तो हम इसे "AppacyUnhandledExceptionPolicy" विकल्प का उपयोग करके हमारे App.config में कर सकते हैं और फिर मैन्युअल रूप से नीचे फाड़ते हैं प्रक्रिया अगर अनचाहे अपवाद मुख्य ऐपडोमेन में था, या उपयुक्त ऐडडोमेन को अनलोड करना अगर यह ऐड-इन में था।

यह सब एक महान मुद्दे को छोड़कर महान काम कर रहा है: अनचाहे अपवाद हमेशा बच्चे से ऐपडोमेन से मुख्य रूप से बबल हो जाते हैं, और यदि वे क्रमिक नहीं हैं, तो वे ऐपडोमेन सीमा को सफलतापूर्वक पार नहीं कर सकते हैं।

इसके बजाय हमें मुख्य एपडोमेन में एक अनचाहे अपवाद के रूप में दिखाई देने वाला एक सीरियलाइजेशन अपवाद प्राप्त होता है, जिससे हमारा आवेदन स्वयं को फाड़ने का कारण बनता है।

मैं इस समस्या का कुछ संभव समाधान के बारे में सोच सकते हैं:

  • हम नीचे बिना क्रिया SerializationExceptions (छी) के लिए प्रक्रिया आंसू नहीं कर सका।

  • हम बच्चे ऐपडोमेन से मुख्य ऐपडोमेन तक प्रचार करने से अपवादों को रोक सकते हैं।

  • हम धारावाहिक सरोगेट्स और सीरियलाइजेशन बाइंडर्स का उपयोग करके, क्रमबद्ध करने योग्य लोगों के साथ अचूक अपवादों को प्रतिस्थापित कर सकते हैं। [संपादित करें: क्यों यह संभव नहीं है के लिए अंत देखने के किराए की कोख का उपयोग कर]

हालांकि पहले एक बहुत भयानक है, और मैं पता लगाना पार के साथ अन्य विकल्पों में से किसी कैसे करना है में असफल किया गया है AppDomain remoting।

क्या कोई सलाह दे सकता है? किसी भी मदद की सराहना की है।

पुन: पेश करने के लिए निम्न App.config के साथ एक सांत्वना आवेदन बनाएँ:

<?xml version="1.0"?> 
<configuration> 
    <runtime> 
    <legacyUnhandledExceptionPolicy enabled="true"/> 
    </runtime> 
</configuration> 

और निम्नलिखित कोड:

class Program 
{ 
    private class NonSerializableException : Exception 
    { 
    } 

    static void Main(string[] args) 
    { 
     AppDomain.CurrentDomain.UnhandledException += MainDomain_UnhandledException; 

     AppDomain childAppDomain = AppDomain.CreateDomain("Child"); 
     childAppDomain.UnhandledException += ChildAppDomain_UnhandledException; 

     childAppDomain.DoCallBack(
      () => new Thread(delegate() { throw new NonSerializableException(); }).Start()); 

     Console.ReadLine(); 
    } 

    static void MainDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
    { 
     Console.WriteLine("Main AppDomain Unhandled Exception: " + e.ExceptionObject); 
     Console.WriteLine(); 
    } 

    static void ChildAppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
    { 
     Console.WriteLine("Child AppDomain Unhandled Exception: " + e.ExceptionObject); 
     Console.WriteLine(); 
    } 
} 



संपादित करें: मैं करने के लिए इस्तेमाल किया परावर्तक देखें कि क्रॉस-एपडोमेन में उपयोग किए जाने वाले बाइनरीफॉर्मेटर तक पहुंच प्राप्त करने का कोई तरीका था या नहीं दूरस्थ, लेकिन यह CrossAppDomainSerializer वर्ग के अंदर इस कोड में समाप्त होता है:

internal static void SerializeObject(object obj, MemoryStream stm) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    RemotingSurrogateSelector selector = new RemotingSurrogateSelector(); 
    formatter.SurrogateSelector = selector; 
    formatter.Context = new StreamingContext(StreamingContextStates.CrossAppDomain); 
    formatter.Serialize(stm, obj, null, false); 
} 

तो यह फ़ॉर्मेटर स्थानीय रूप से विधि में बनाता है, और वहाँ स्पष्ट रूप से अपने ही सरोगेट संलग्न करने के लिए कोई रास्ता नहीं है ... मैं यह किसी भी बनाता है लगता है उस दिशा में अधिक प्रयास व्यर्थ।

+0

अरे जेम्स, क्या आपको कभी इसका समाधान मिला? – Joshjje

+0

@ जोशजे, एक अच्छा समाधान नहीं है ... हम केवल प्रत्येक ऐपडोमेन के भीतर अनचाहे अपवादों को संभालने के लिए समाप्त हुए, और फिर ऐपडोमेन को वहां से खुद को उतारने दिया। यह स्पष्ट रूप से इस प्रणाली को सेट करने के लिए प्रत्येक ऐड-इन पर भरोसा करने की आवश्यकता है, जो हम अपने आवेदन के लिए शुक्रिया अदा कर सकते हैं। हालांकि मुझे मुख्य ऐपडोमेन के भीतर से पूरी प्रक्रिया को प्रबंधित करने का कोई तरीका नहीं मिला। –

उत्तर

2

मैं रिमोट एप्लिकेशन डोमेन में अपवादों को संभालता हूं। सबसे पहले मैं अपवाद हैंडलिंग कोड के साथ एक नई असेंबली तैयार करूंगा और फिर मैं इसे बाल एप्लिकेशन डोमेन में लोड करूंगा।

निम्नलिखित कोड कुछ विचार देना चाहिए।

class Program { 
    private class NonSerializableException : Exception { } 

    static void Main(string[] args) { 
     var childAppDomain = AppDomain.CreateDomain("Child"); 
     Console.WriteLine("Created child AppDomain #{0}.", childAppDomain.Id); 

     // I did not create a new assembly for the helper class because I am lazy :) 
     var helperAssemblyLocation = typeof(AppDomainHelper).Assembly.Location; 
     var helper = (AppDomainHelper)childAppDomain.CreateInstanceFromAndUnwrap(
       helperAssemblyLocation, typeof(AppDomainHelper).FullName); 
     helper.Initialize(UnloadHelper.Instance); 

     childAppDomain.DoCallBack(
      () => new Thread(delegate() { throw new NonSerializableException(); }).Start()); 

     Console.ReadLine(); 
    } 

    private sealed class UnloadHelper : MarshalByRefObject, IAppDomainUnloader { 
     public static readonly UnloadHelper Instance = new UnloadHelper(); 

     private UnloadHelper() { } 

     public override object InitializeLifetimeService() { 
      return null; 
     } 

     public void RequestUnload(int id) { 
      // Add application domain identified by id into unload queue. 
      Console.WriteLine("AppDomain #{0} requests unload.", id); 
     } 
    } 
} 

// These two types could be in another helper assembly 

public interface IAppDomainUnloader { 
    void RequestUnload(int id); 
} 

public sealed class AppDomainHelper : MarshalByRefObject { 
    public void Initialize(IAppDomainUnloader unloader) { 
     AppDomain.CurrentDomain.UnhandledException += (sender, e) => 
       unloader.RequestUnload(AppDomain.CurrentDomain.Id); 
    } 
} 
+0

धन्यवाद mgronber, लेकिन इस समाधान के साथ भी NonSerializableException अभी भी अभिभावक AppDomain को एक अनचाहे SerializationException के रूप में प्रचारित हो जाता है। मैं SerializationException को बच्चे एपडोमेन से आने के रूप में नहीं पहचान सकता, जो मुझे इसे अनदेखा करने या किसी अन्य अनचाहे अपवाद के रूप में इसका इलाज करने और आवेदन को समाप्त करने के लिए मजबूर कर रहा है। –

+0

बस जोड़ने के लिए, हम वास्तव में डिस्पैचर को संभालने के लिए जो प्रस्ताव दे रहे हैं, उसके लिए एक समान तकनीक का उपयोग करते हैं। अनचाहे अपवाद घटनाएं ... यह वहां अच्छी तरह से काम करती है क्योंकि आप अपवाद को संभालने के रूप में चिह्नित कर सकते हैं और यह आगे प्रचार नहीं करेगा। AppDomain.UnhandledException दुख की बात नहीं करता है और हमेशा मुख्य ऐपडोमेन तक अपवाद को बुलबुला करता है :( –

+0

आप बच्चे डोमेन में कोड कैसे निष्पादित करते हैं? क्या आप एक सहायक विधि का उपयोग कर सकते हैं जो कोड को कॉल करता है और शेष अपवादों को पकड़ता है अनचाहे? – mgronber

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