2016-08-02 5 views
16

मैं सी ++ से सी # तक अपेक्षाकृत छोटी सेवा को फिर से लिखने की संभावना की जांच कर रहा हूं। सेवा में दो मुख्य कार्य हैं:क्या मैं कुछ धागे अकेले छोड़ने के लिए .NET जीसी बता सकता हूं?

  1. थोड़ी देर में HTTP अनुरोध निष्पादित करें। उनमें कई उच्च स्तरीय कार्य शामिल हैं जैसे JSON एन्कोडिंग/डिकोडिंग, बेस 64 एन्कोडिंग/डिकोडिंग, और HTTP अनुरोध स्वयं, जिसके लिए सी ++ अद्भुत नहीं है;
  2. कई वास्तविक समय, ऑडियो-संबंधित कार्यों को निष्पादित करें जिनमें हार्ड डेडलाइन हैं, जिसके लिए सी # शानदार नहीं है।

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

बात यह है कि वास्तविक समय के हिस्से में कठिन समय सीमा है, इसलिए मैं पुस्तकालय के धागे पर जीसी विराम को वास्तव में बर्दाश्त नहीं कर सकता। अपने कोड के पक्ष में, वेब अनुरोधों के बीच जीसी चलाने के लिए बहुत समय होना चाहिए, लेकिन मैं बर्दाश्त नहीं कर सकता कि यह लाइब्रेरी में डेटा को खिलाने की कोशिश कर रहा है।

I found कि मैं एक महत्वपूर्ण खंड बना सकता हूं जिसमें कचरा कलेक्टर GC.TryStartNoGCRegion() का उपयोग शुरू नहीं करेगा, जो समस्या का आधा हल करता है।

हालांकि, मुझे अभी भी पता नहीं है कि .NET जीसी को अकेले विशिष्ट थ्रेड छोड़ने का तरीका है जो प्रबंधित कोड नहीं चलाता है। क्या यह संभव है?

+0

देखें [यह पोस्ट] (http://stackoverflow.com/questions/6005865/prevent-net-garbage-collection-for-short-period-of-time)। यह सभी प्रकार की चेतावनियों के साथ आता है। –

+0

@ स्कॉटहैनन, मैंने भी उस पर ठोकर खाई (मैंने इसे जीसी.TryStartNoGCRegion के अनुच्छेद में जोड़ा)। मुझे नहीं लगता कि यह कचरे के संग्रह से धागे को छोड़कर कुछ भी दिखाता है। – zneak

+6

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

उत्तर

1

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

private bool _running = true; 
    private int _workCounter = 0; 
    private AutoResetEvent _workFlag = new AutoResetEvent(false); 
    private void RunNoGCNativeCode(params object[] args) 
    { 
     // Increase the work counter to determine how many requests are being processed 
     if (Interlocked.Increment(ref _workCounter) == 1) 
     { 
      // Try to start a No GC Region 
      GC.TryStartNoGCRegion(1 * 1024 * 1024 * 1024, true); 
     } 
     // TODO: Prep data and execute your native code 
     // TODO: Process response 
     // TODO: Dispose of anything that is no longer in use and null objects as needed 
     if (Interlocked.Decrement(ref _workCounter) == 0 && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) 
     { 
      GC.EndNoGCRegion(); 
     } 
     // Notify Manual Collection thread work has been completed 
     _workFlag.Set(); 
    } 

एक अलग धागा पर ...

private void WaitForNoWorkThenGC() 
    { 
     // Continue running thread while in use 
     while (_running) 
     { 
      // Wait for some work to be complete 
      _workFlag.WaitOne(); 
      // If there is no work being processed call GC.Collect() 
      if (_workCounter == 0) 
      { 
       GC.Collect(); 
      } 
     } 
    } 

यह आपको नियंत्रित करने में सहायता चाहिए जब जीसी प्रभाव को कम करने के लिए होता है आपके आवेदन पर

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

हालांकि दो संभावित समाधान हैं जिन्हें आप देख सकते हैं।

  1. Garbage Collection Notifications का उपयोग करके निगरानी करने के लिए जब जीसी एक पूर्ण कचरा संग्रह के पास आ रहा है। संभावित रूप से यदि आप संग्रह बिंदु तक पहुंचने से पहले मैन्युअल रूप से कुछ मेमोरी मुक्त करते हैं तो आप कचरा संग्रह से बच सकते हैं।
  2. अलग-अलग एप्लिकेशन प्रक्रियाओं में विभिन्न प्रकार के अनुरोध चलाएं? या उन्हें अलग-अलग एप्लिकेशन प्रक्रियाओं को पास करने के लिए पास करें। इस तरह प्रत्येक एप्लिकेशन संदर्भ साझा नहीं करता है और कचरा संग्रह अलग से संभाला जाएगा।
+1

मैं शोध प्रयास की सराहना करता हूं, लेकिन मैं यह इंगित करना चाहता हूं कि * दस्तावेज सबूत है कि वर्कस्टेशन कचरा कलेक्टर देशी कोड चला रहे थ्रेड को बाधित नहीं करेगा। देखें [कचरा संग्रह की बुनियादी बातों] (https://msdn.microsoft.com/en-us/library/ee787088 (v = vs.110) .aspx # workstation_and_server_garbage_collection), "वर्कस्टेशन और सर्वर कचरा संग्रह की तुलना" पर स्क्रॉल करें। – zneak

+0

आह हाँ मेरा उत्तर प्रबंधित कोड चलाने वाले धागे के लिए विशिष्ट है। आपके .NET एप्लिकेशन के पहले और बाद में आपके मूल कोड को कॉल कर रहा है। दूसरे शब्दों में आपने अपने स्वयं के प्रश्न का उत्तर दिया, "जीईटी के दौरान मूल कोड निष्पादित धागे को निलंबित करने के लिए .NET को कैसे बताना है? - वर्कस्टेशन जीसी मोड का उपयोग करने के लिए अपने एप्लिकेशन को कॉन्फ़िगर करें, देखें: Elementhttps: //msdn.microsoft.com/en- हमें/लाइब्रेरी/एमएस 22 9 357% 28 वी = बनाम 10% 2 9 .aspx? एफ = 255 और एमएसपीपीआरआर = -2147217396 " – xer21

+0

@zneak मैंने प्रतिबिंबित करने के लिए अपनी प्रतिक्रिया अपडेट की है। – xer21

-2

यह जाँच नहीं था लेकिन, मैं धागा, या कार्य जो कुछ भी आप की तरह का उपयोग वारिस होगा: तो तुम यह आम तौर पर उपयोग कर सकते हैं

var newThread = new SuppressedThread(DoWork); 
newThread.Start(42); 

क्या कर

public class SuppressedThread : Thread 
{    
    protected override void Finalize() 
    { 
     try 
     { 
      // kill what you want 
     } 
     finally 
     { 
      base.SupressFinalizeFinalize(); 
     } 
    } 
} 

public class SuppressedThread : Thread, IDisposable 
{  
    protected override void Dispose() 
    { 
     try 
     { 
      // kill what you want 
     } 
     finally 
     { 
      GC.SupressFinalize(); 
     } 
    } 
} 

आपको लगता है?

+3

इसमें कई समस्याएं हैं। 1) 'थ्रेड' सील कर दिया गया है; आप इससे प्राप्त नहीं कर सकते हैं। 2) भले ही आप इससे प्राप्त कर सकें, यह केवल थ्रेड के जीसी को ही रोक देगा, न कि थ्रेड पर बनाए गए ऑब्जेक्ट्स। 3) 'अंतिमकरण' विधि को सी # में ओवरराइड नहीं किया जा सकता है। इसके बजाय फाइनलाइज़र सिंटैक्स का उपयोग किया जाता है, जैसे ~ ~ Foo() '। – vcsjones

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