2012-05-17 19 views
5

मेरे पास .NET 3.5 में एक बहु-थ्रेड विंडो सेवा है, और मुझे एक से अधिक धागे बनाए जाने पर सेवा को ठीक से रोकने में कुछ परेशानी हो रही है।एक बहु थ्रेडेड विंडोज सेवा को रोकना

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

//Tried with and without this attribute with no success... 
    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)] 
    public void StartThreadPool() 
    { 
     while (serviceStarted) 
     { 
      ProcessInfo input = new ProcessInfo(); 

      try 
      { 
       int? NumPendingRequests = GetItems(50, (Guid?)input.ProcessID); 

       if (NumPendingRequests > 0) 
       { 
        input.ProcessType = 1; 
        input.ProcessID = Guid.NewGuid(); 
        ThreadPool.QueueUserWorkItem(new WaitCallback(new DispatchManager().ProcessRequestList), input); 
       } 
      } 
      catch (Exception ex) 
      { 
       //Some Logging here 
      } 
     } 

     DeliveryConstant.StopService = true; 
    } 

मैं एक अलग वर्ग में एक स्थिर चर बनाया:

protected override void OnStart(string[] args) 
    { 
     try 
     { 
      //Global variable that is checked by threads to learn if service was stopped 
      DeliveryConstant.StopService = false; 
      bool SetMaxThreadsResult = ThreadPool.SetMaxThreads(10, 10); 

      ThreadStart st = new ThreadStart(StartThreadPool); 
      workerThread = new Thread(st); 
      workerThread.IsBackground = true; 
      serviceStarted = true; 
      workerThread.Start(); 
     } 
     catch (Exception ex) 
     { 
      //Log something; 
     } 

यहाँ StartThreadPool विधि है:

जब सेवा प्रारंभ कर रहा है, मैं मुख्य प्रक्रिया को संभालने के लिए एक पृष्ठभूमि धागा बनाने सेवा को रोक दिया गया था कि धागे को सूचित करने के लिए। अंत में OnStop विधि

 public static bool StopService; 

,:

protected override void OnStop() 
    { 
     DeliveryConstant.StopService = true; 

     //flag to tell the worker process to stop 
     serviceStarted = false; 

     workerThread.Join(TimeSpan.FromSeconds(30)); 
    } 

ProcessRequestList विधि में, पर जब इस चर के लिए मूल्य सच है, सभी धागे मुख्य लूप (एक प्रत्येक पाश के लिए) बंद कर देना चाहिए प्रत्येक foreach के अंत, मैं StopService चर के मूल्य की जांच। यदि सही है, तो मैंने लूप तोड़ दिया।

यहां समस्या है: धागे 50 वस्तुओं के टुकड़ों में बनाए जाते हैं। मैं 50 आइटम या डेटाबेस में कम है, तो केवल एक ही धागा बनाया जाता है, और सब कुछ खूबसूरती से काम करता है। जब मेरे पास 50 से अधिक आइटम हैं, तो एकाधिक थ्रेड बनाए जाएंगे, और जब मैं सेवा को रोकने का प्रयास करता हूं, तब तक यह तब तक नहीं रुकता जब तक कि सभी पृष्ठभूमि धागे पूरा नहीं हो जाते।

लॉग से, मैं देख सकता हूं कि ऑन थॉप्स विधि केवल सभी धागे पूर्ण होने के बाद ही निष्पादित की जाती है।

कोई सुराग जिसे ठीक करने के लिए बदला जा सकता है?

+0

जबकि लूप में नींद (50) डालने का प्रयास करें। –

+0

ऐसा लगता है कि आपने कोड का सबसे महत्वपूर्ण हिस्सा शामिल नहीं किया है। यह ProcessRequestList विधि कार्यान्वयन है। –

+0

क्या आप कोड दिखा सकते हैं जहां StopService से पूछताछ की जाती है? स्थैतिक var पर CancellationToken का उपयोग करने में देखें, क्योंकि यह उस तरह की चीज़ के लिए बनाया गया है। – hatchet

उत्तर

9

यह blog answer कहता है कि सभी थ्रेडपूल कार्यों को पूरा होने तक ऑनस्टॉप को तब तक नहीं बुलाया जाता है, जो मुझे खबर है लेकिन आपकी समस्या को समझाएगा।

मैं कई मल्टी-थ्रेडेड विंडोज सेवा को मैदान में उतारा है, लेकिन मैं अपने ही पृष्ठभूमि धागे बनाने के बजाय ThreadPool का उपयोग के बाद से इन लंबे समय से चल धागे हैं पसंद करते हैं। मैं कार्यकर्ता वर्गों को तुरंत चालू करता हूं और धागे पर अपनी DoWork() विधि लॉन्च करता हूं। मैं भी एक बंद संकेत के लिए जाँच करें और सिर्फ एक वैश्विक चर के खिलाफ परीक्षण के बजाय स्थिति पारित करने के लिए शुरू वर्ग के लिए कॉलबैक के उपयोग करने के लिए पसंद करते हैं।

+0

आपने ठीक से इस मुद्दे को खींचा। बहुत धन्यवाद! यह बहुत कुछ है जो मैंने कहा था कि चल रहा था, लेकिन यह नहीं पता था कि यह एक अपेक्षित व्यवहार था। यह जानकर, अब मैं कामकाजी धागे में सेवा की स्थिति की जांच कर रहा हूं, और यह एक आकर्षण की तरह काम कर रहा है। निश्चित नहीं है (फिर भी) प्रदर्शन के लिए यह कितना महंगा होगा। धन्यवाद! – Roberto

+0

रॉबर्टो, क्या आप अपने प्रश्न में अपने समाधान को पोस्ट करना चाहते हैं, या यह है कि बुलियन स्टॉप सेवा चर क्या है? – PAULDAWG

3

आप याद कर रहे हैं स्मृति बाधाओं के आसपास StopService करने तक पहुँचता है, यदि आप एक से अधिक CPU है एक समस्या हो सकती है। साझा चर के सभी पहुंच के लिए किसी भी संदर्भ वस्तु को बेहतर लॉक करें।

object @lock; 

... 

lock (@lock) 
{ 
    StopService = true; 
} 

संपादित: उदाहरण के लिए: के रूप में एक और उत्तर से पता चला है, इस मुद्दे एक लॉकिंग समस्या नहीं था, लेकिन मैं multithread तुल्यकालन योजनाओं के साथ जांच करने के लिए एक चीज के रूप में यहाँ इस उत्तर छोड़ रहा हूं।

बनाना साझा चर अस्थिर रूप में अच्छी तरह से कई मामलों में काम करेगा, लेकिन इसे और अधिक सही साबित करने के लिए है क्योंकि यह पूरा बाड़ उत्सर्जन नहीं जटिल है।

+0

यह परमाणुता के बारे में नहीं है लेकिन स्मृति बाधाओं के बारे में है। परमाणुता का मतलब है कि अन्य धागा यह सब देखेगा - या कोई नहीं। मेमोरी बाधा (यहां दो प्रकार के खेल खेलते हैं, लेकिन चलो इसे सादगी के लिए छोड़ दें) सुनिश्चित करता है कि "कोई भी" मामला नहीं होता है। –

+0

इसे टैग किया गया है C#, जावा – hatchet

+0

ओह। मैं सवालों के बीच कूद रहा था। यहाँ उस misedit वापस घुमाया। –