2009-05-06 14 views
7

के साथ एमवीपी में एसिंक्रोनस कॉल के लिए सर्वोत्तम अभ्यास मैं WinForms प्रोजेक्ट में मॉडल-व्यू-प्रेजेंटर पैटर्न का उपयोग कर रहा हूं और एक समस्या (कई लोगों में) है जो मेरे पास है जब प्रपत्र प्रस्तुतकर्ता को कुछ करने के लिए कहता है और फिर है अप्रतिबंधक जबकि प्रस्तुतकर्ता इसे करने के लिए चला जाता है। सौभाग्य से मेरी परियोजना में मुझे सभी प्रस्तुतकर्ताओं को असीमित कॉल करने में कोई समस्या नहीं है सवाल यह है कि यह वास्तव में कैसे करना है?WinForms

प्रत्येक प्रस्तोता कॉल बस एक नया धागा निर्माण में लिपटे किया जाना चाहिए? *

new Thread(()=>_presenter.DoSomething()).Start(); 

सर्वोत्तम प्रथाओं यहाँ क्या हैं? क्या होगा यदि उपयोगकर्ता "आप जो कर रहे हैं उसे छोड़ दें" बटन दबाता है? मैं कृपा से कैसे निरस्त करूं?

। * वास्तविक मैं शायद सिर्फ एक प्रॉक्सी के कुछ प्रकार प्रस्तोता पर नहीं बल्कि WinForm में धागा निर्माण डालने से प्रयोग करेंगे यह करने के लिए

+0

यहां कोई वास्तविक भागीदारी देखने के लिए आश्चर्यचकित नहीं है। मुझे भी इसमें दिलचस्पी होगी। – Houman

उत्तर

2

मैं केवल दावा कर सकता हूं कि मैंने इस बारे में सोचा है (आपके प्रश्न को पढ़ने से पहले;)। सबसे पहले मैं उन स्थानों को रिग कर दूंगा जहां यह वास्तव में मायने रखता है; उदाहरण के लिए डीबी एक्सेस चोकपॉइंट। यदि कोई ऐसा स्थान है जिसे "यूआई" संदर्भ में निष्पादित नहीं किया जाना चाहिए (आप इसे यूआई थ्रेड में http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx से सहेज सकते हैं और फिर बाद में गैर-यूआई सिंक्रनाइज़ेशन संदर्भ में तुलना करें) तो इसके बारे में Debug.BitchAndMoan()। अब और गणना (जो "सभी" स्पष्ट रूप से अपने स्वयं के कई गुनाओं में अलग होना चाहिए, सही;) उस पर जोर देना चाहिए।

मुझे लगता है कि आपको कम से कम प्रस्तुतकर्ता फ़ंक्शन को निष्पादन योग्य प्रकार के निष्पादन के माध्यम से कॉन्फ़िगर करने योग्य प्रकार का निष्पादन करना चाहिए, जिसे प्रॉक्सी द्वारा पालन किया जाता है। (बस अगर आप धारावाहिक फैशन में कुछ करना चाहते हैं)।

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

मेरा अनुभव यह है कि यह आमतौर पर घटनाओं (एससीएसएफ शैली) का उपयोग करके आसपास काम करता है। अगर इसे खरोंच से कर रहे हैं, तो मैं प्रॉक्सी रास्ता जाऊंगा क्योंकि एससीएसएफ इतने सारे तरीकों से दर्द रहा है कि मुझे इसकी डिजाइनरों की संवेदना पर संदेह है।

+0

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

+1

मैं _think_ बीडब्ल्यू एक ज्ञात कार्य के लिए अधिक मतलब है जो हमेशा "समान" चीज करता है, इसलिए स्पॉन्गिंग थ्रेड बेवकूफ होना चाहिए .NET यहाँ। आप जो करते हैं उसके आधार पर आप थ्रेडपूल का उपयोग करना चाह सकते हैं: http://msdn.microsoft.com/en-us/library/ms973903.aspx। डिफ़ॉल्ट थ्रेडपूल द्वारा 25 गहरा होता है, इसलिए आप इसे कॉन्फ़िगर/परीक्षण करने में देख सकते हैं (यह सीमा लागू नहीं होती है यदि आप हमेशा एक नया धागा उत्पन्न करते हैं) –

0

क्यों प्रॉक्सी पैटर्न आप कॉल पीठ के एक जोड़े को स्वीकार का उपयोग नहीं कर सकता परिणाम लौटने या निरस्त करने के लिए?

+0

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

4

मैं आमतौर पर किसी भी कार्रवाई कर सकते हैं (वास्तविक) एक दूसरे या दो से अधिक एक अलग काम में लेने की जगह है, कुछ की तरह:

public interface ITaskExecutor : IDisposable 
{ 
    void BeginTask(ITask task); 
    void TellTaskToStop(); 
} 
:

public interface ITask 
{ 
    void ExecuteTask (ITaskExecutionContext context); 
    void AfterSuccess(ITaskExecutionContext context); 
    void AfterFailure(ITaskExecutionContext context); 
    void AfterAbortion(ITaskExecutionContext context); 
} 

मैं भी चल रहा है इस तरह के कार्यों के लिए एक अमूर्त है

public class BackgroundTaskExecutor : ITaskExecutor 
{ 
    public void BeginTask(ITask task) 
    { 
     this.task = task; 
     worker = new BackgroundWorker(); 
     worker.DoWork += WorkerDoWork; 
     worker.RunWorkerCompleted += WorkerRunWorkerCompleted; 
     worker.WorkerSupportsCancellation = true; 

     worker.RunWorkerAsync(); 
    } 

    ... 
} 
:

इस ITaskExecutor के कार्यान्वयन में से एक BackgroundWorker उपयोग कर रहा है

मैं निर्भरता इंजेक्शन और आईओसी पर चीजों को एक साथ तार करने के लिए भारी निर्भर करता हूं। प्रस्तोता में तो मैं सिर्फ फोन की तरह कुछ:

GoAndDontReturnUntilYouBringMeALotOfMoneyTask task = new GoAndDontReturnUntilYouBringMeALotOfMoneyTask(parameters); 
taskExecutor.BeginTask(task); 

रद्द/निरस्त बटन तो तार कर रहे हैं वे निरस्त करने के लिए कार्य प्रबंधक/कार्य बताओ।

यह वास्तव में यहां प्रस्तुत करने से थोड़ा अधिक जटिल है, लेकिन यह सामान्य विचार है।

+0

मैं निष्पादन, आफ्टरसेफ, आफ्टरफेलर, आफ्टरबॉर्टर के बाद लैम्बडास में पास करूंगा लेकिन इसके अलावा, अच्छी सलाह। –

+0

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