2011-03-30 16 views
6

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

तो बच्चे एपडोमेन में एक ईवेंट लूप में चलने वाला धागा है, यह एक मार्शलबीरफॉबजेक्ट के माध्यम से घटनाओं को पारित करता है जो एक समवर्ती कतार में सामान चिपकता है। मैं बच्चे ऐपडोमेन को रोकना और अनलोड करना चाहता हूं और एक नया निर्माण करना चाहता हूं।

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

मेरे पास कुछ उदाहरण कोड है जो दिखाता है कि इसका सेटअप कैसे और मैं इसे मारने के लिए अनलोड कैसे कह सकता हूं, मैं इसे अनूठा अनलोडिंग की अनुमति देने के लिए कैसे संशोधित कर सकता हूं और कभी भी कई बच्चे ऐपडोमेन नहीं कर सकता?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Security; 
using System.Security.Permissions; 
using System.Reflection; 
using System.Threading; 

namespace TestAppDomains 
{ 
    /// <summary> 
    /// Calls to methods magically get transfered to the appdomain it was created in because it derives from MarshalByRefObject 
    /// </summary> 
    class MarshalProxy : MarshalByRefObject 
    { 
     public AppDomain GetProxyAppDomain() 
     { 
      return AppDomain.CurrentDomain; 
     } 

     public void SayHello() 
     { 
      Console.WriteLine("MarshalProxy in AD: {0}", AppDomain.CurrentDomain.FriendlyName); 
     } 

     public void RunLoop() 
     { 
      try 
      { 
       while (true) 
       { 
        Console.WriteLine("RunLoop {0} in {1}", DateTime.Now.ToLongTimeString(), AppDomain.CurrentDomain.FriendlyName); 
        Thread.Sleep(1000); 
       } 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine("You killed me! {0}", ex); 
       Thread.Sleep(200); //just to make sure the unload is really blocking until its done unloading 
       // if the sleep is set to 2000 then you will get a CannotUnloadAppDomainException, Error while unloading appdomain. (Exception from HRESULT: 0x80131015) thrown from the .Unload call 
      } 
     } 

     static int creationCount = 1; 
     public static MarshalProxy RunInNewthreadAndAppDomain() 
     { 
      // Create the AppDomain and MarshalByRefObject 
      var appDomainSetup = new AppDomainSetup() 
      { 
       ApplicationName = "Child AD", 
       ShadowCopyFiles = "false", 
       ApplicationBase = Environment.CurrentDirectory, 
      }; 

      var childAppDomain = AppDomain.CreateDomain(
       "Child AD " + creationCount++, 
       null, 
       appDomainSetup, 
       new PermissionSet(PermissionState.Unrestricted)); 

      var proxy = (MarshalProxy)childAppDomain.CreateInstanceAndUnwrap(
       typeof(MarshalProxy).Assembly.FullName, 
       typeof(MarshalProxy).FullName, 
       false, 
       BindingFlags.Public | BindingFlags.Instance, 
       null, 
       new object[] { }, 
       null, 
       null); 

      Thread runnerThread = new Thread(proxy.RunLoop); 
      runnerThread.Name = "MarshalProxy RunLoop"; 
      runnerThread.IsBackground = false; 
      runnerThread.Start(); 

      return proxy; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("I am running in AD: {0}", AppDomain.CurrentDomain.FriendlyName); 

      var proxy = MarshalProxy.RunInNewthreadAndAppDomain(); 
      proxy.SayHello(); 

      while (true) 
      { 
       Console.WriteLine("Press enter to kill and restart proxy"); 
       Console.WriteLine(); 
       Console.ReadLine(); 

       Console.WriteLine("Unloading"); 
       AppDomain.Unload(proxy.GetProxyAppDomain()); 
       Console.WriteLine("Done unloading"); 

       proxy = MarshalProxy.RunInNewthreadAndAppDomain(); 
      } 
     } 
    } 
} 
+2

पहले थ्रेड को पहले से रोकें। –

उत्तर

8

निम्नलिखित

runnerThread.IsBackground = true; 

प्रयास करें और, हाँ, वहाँ AppDomain का कोई सुंदर उतराई है अगर आप धागे पहले नहीं रुके।

2

स्थिति अनिवार्य रूप से वही है जैसे कि दो ऐपडोमेन अलग प्रक्रियाएं थीं, इसलिए आपको कुछ प्रकार के आईपीसी का उपयोग करने की आवश्यकता है। लूप को रोकने के लिए पूछते समय एक विकल्प बच्चे ऐपडोमेन में इवेंट हैंडल पास करना होगा। लूप बाहर निकलने से पहले घटना को संकेत दे सकता है। घटना को प्रतीक्षा करने के लिए कुछ समय लूप देने के लिए प्रतीक्षा करें। यदि आप समय निकालते हैं, तो आप एक मोटा अनलोड कर सकते हैं।

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