2011-10-10 7 views
6

मैं एक ऐप लिख रहा हूं, जहां अधिकांश काम पृष्ठभूमि धागे (10 - 500 धागे) द्वारा किया जाता है।किसी एप्लिकेशन को रोक/फिर से शुरू करने की कार्यक्षमता कैसे जोड़ें?

मैं विराम/फिर से शुरू करने की कार्यक्षमता जोड़ना चाहता हूं।

इससे पहले, आप थ्रेड के साथ ऐसा कर सकते हैं। सस्पेंड और थ्रेड। रेज़्यूम। लेकिन उन कार्यों को अब अप्रचलित माना जाता है।

क्या कोई ऐसी चीज है जो मुझे समान आसानी से ऐसा करने देगी?

मैं C#

+0

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

+2

एक प्रक्रिया में 500 धागे एक * भारी * धागे की संख्या है, खासकर यदि उनमें से एक गुच्छा अधिक समय सो रहा है। मेरी सलाह है कि मशीन में प्रोसेसर की तुलना में कोई और थ्रेड का उपयोग करने के लिए अपने आर्किटेक्चर को फिर से डिजाइन न करें। सी # में धागे बहुत "भारी" हैं; आपको नौकरी पाने के लिए आवश्यक न्यूनतम न्यूनतम बनाना चाहिए। आप क्या कर रहे हैं कि आप इतने सारे धागे बना रहे हैं? –

+0

यह एक वेब क्रॉलिंग ऐप है। प्रत्येक थ्रेड अपने अधिकांश समय कुछ वेब सर्वर से प्रतिक्रिया के लिए इंतजार कर रहा है, सभी धागे एक ही स्थान पर शुरू हो जाते हैं, और जब उपयोगकर्ता "रोकें" बटन दबाता है तो रोका जाना चाहिए। ऐप आमतौर पर स्मृति की 700m-2G लेता है, और जब तक ऐसा करने का कोई बेहतर तरीका न हो तब तक मैं इसके साथ ठीक हूं; यहां तक ​​कि 500 ​​धागे पर, ऐप आमतौर पर –

उत्तर

2

सी # में एक उच्च प्रदर्शन क्रॉलर लिखा, मैं कुछ अधिकार है कि स्पष्ट रूप से प्रबंध दर्जनों या धागे के सैकड़ों जाने के लिए सबसे अच्छा तरीका नहीं है के साथ कह सकते हैं। यह किया जा सकता है (मैंने किया), लेकिन चरम में दर्दनाक है।

ने कहा। । ।

आपके आवेदन तरह से मुझे लगता है कि लिखा है, तो प्रत्येक धागा करता है कुछ इस तरह:

while (!Shutdown) 
{ 
    // get next url to crawl from somewhere 
    // download the data from that url 
    // do something with the data 
} 

डाउनलोड के बीच धागे को रोकने का बहुत आसान है। मैं दो ManualResetEvent उदाहरण बनाने का सुझाव दूंगा: एक जारी रखने के लिए, और शटडाउन के लिए एक। ताकि सभी क्रॉलर धागे उन तक पहुँच सकते ये static हैं:

static ManualResetEvent ShutdownEvent = new ManualResetEvent(false); 
static ManualResetEvent ContinueEvent = new ManualResetEvent(true); 

फिर, प्रत्येक धागा एक पाश में WaitAny उपयोग करता है:

WaitHandle[] handles = new WaitHandle[] { ShutdownEvent, ContinueEvent }; 
while (true) 
{ 
    int handle = WaitHandle.WaitAny(handles); // wait for one of the events 
    if (handle == -1 || handle >= handles.Length) 
    { 
     throw new ApplicationException(); 
    } 

    if (handles[handle] = ShutdownEvent) 
     break; // shutdown was signaled 

    if (handles[handle] == ContinueEvent) 
    { 
     // download the next page and do something with the data 
    } 
} 

ध्यान दें कि जब मैं handles सरणी परिभाषित, मैं निर्दिष्ट ShutdownEvent पहले। इसका कारण यह है कि यदि एकाधिक आइटम संकेतित होते हैं, तो WaitAny संकेतित वस्तु से मेल खाने वाली सबसे कम अनुक्रमणिका देता है। यदि सरणी दूसरे क्रम में आबादी में थी, तो आप पहले रुकने के बिना बंद नहीं कर पाएंगे।

अब, यदि आप थ्रेड बंद करना चाहते हैं, तो ShutdownEvent.Set पर कॉल करें। और यदि आप थ्रेड को रोकना चाहते हैं, तो ContinueEvent.Reset पर कॉल करें जब आप थ्रेड को फिर से शुरू करना चाहते हैं, तो ContinueEvent.Set पर कॉल करें।

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

2

अपने app क्या करता है में सॉफ्टवेयर लिख रहा हूँ?

500 धागे बहुत अधिक हैं - यह सिर्फ ढेर के लिए 1/2 जीबी की प्रतिबद्ध स्मृति है। और फिर आपके पास सभी संदर्भ स्विचिंग हैं।

अच्छा है कि आप Suspend और Resume कॉल से छुटकारा पाने के लिए चाहते हैं, लेकिन मैं सुझाव है कि आप पहली बार अपने वास्तुकला पर एक नजर है - आप एपीएम विधियों (BeginXXX/EndXXX) को स्थानांतरित कर सकते हैं?

+0

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

2

मैं जो कहने जा रहा हूं उसके बारे में एक चेतावनी के रूप में: यह स्पष्ट नहीं है कि आपका ऐप क्या करता है; टीपीएल, पृष्ठभूमि श्रमिक आदि जैसे थ्रेड पूल धागे का उपयोग करने के लिए कई सरल तरीके हैं

हालांकि, अगर आपके पास बनाए गए थ्रेड हैं (थ्रेडपूल नहीं) और आप उन्हें संवाद करना चाहते हैं तो मॉनिटर.एट और मॉनीटर का उपयोग करें। एक बुलियन अवरुद्ध स्थिति के साथ पल्स।

उदाहरण के लिए:

bool _isPaused; 

void DoWork() 
{ 
     while (true) 
     { 
      lock (_locker) 
      { 
       while (_isPaused) Monitor.Wait(_locker); 

       // your worker code here 

      } 

     } 
} 
     // 
void UnPause() 
{ 
     lock (_locker) 
     { 
      _isPaused=false; 
      Monitor.PulseAll(_locker); 
     } 
} 
1

नहीं वास्तव में। निलंबित/फिर से शुरू करना वास्तव में सरल है और जब तक वे आपके ऐप को क्रैश नहीं करते हैं, ठीक है। मेमोरी मैनेजर या फाइल सिस्टम लॉक होने वाले थ्रेड को निलंबित करके :(

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

आप @Andrey द्वारा सुझाए गए वैश्विक बूलियन 'isRunning' ध्वज की जांच करके वास्तविक निलंबन कर सकते हैं, और अगर निलंबन की आवश्यकता है, तो वैश्विक मैनुअल रीसेट पर रोकें। निलंबित करने के लिए, ईवेंट को साफ़ करें और फिर ध्वज। फिर से शुरू करने के लिए, ध्वज सेट करें और फिर घटना।

यदि ग्लोबल्स का उपयोग करना आपको उल्टी लग रहा है, तो आप सीटीओ को ध्वज, घटना और 'निलंबित(),' फिर से शुरू करें) 'और' checkForSuspend() 'विधियों वाले कुछ वर्गों का एक सामान्य उदाहरण पारित कर सकते हैं।

Rgds, मार्टिन

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