2013-02-27 11 views
6

से पहले वापसी मैं एक एएसपी.नेट एमवीसी 4 वेब अनुप्रयोग पर काम कर रहा हूं। मैं .NET 4.5 का उपयोग कर रहा हूं और नई एसिंक्रोनस एपीआई का लाभ लेने की कोशिश कर रहा हूं।एसिंक कार्य पूर्ण

मेरे पास कुछ स्थितियां हैं जहां मैं बाद में चलाने के लिए एसिंक टास्क शेड्यूल करना चाहता हूं, जबकि मैं तुरंत तुरंत एक महत्वपूर्ण मूल्य वापस लौटाता हूं। उदाहरण के लिए, यहाँ एक विधि "लॉगिन" जो मैं एक नया सत्र आईडी जल्दी से जल्दी वापस करना चाहते है, लेकिन एक बार मैं SessionID लौटा दिया है मैं पुराने समय सीमा समाप्त हो SessionID के बाहर साफ करने के लिए करना चाहते हैं:

public async Task<Guid> LogIn(string UserName, string Password) 
{ 
    //Asynchronously get ClientID from DB using UserName and Password 

    Session NewSession = new Session() 
    { 
     ClientID = ClientID, 
     TimeStamp = DateTime.Now 
    }; 
    DB.Sessions.Add(NewSession); 
    await DB.SaveChangesAsync(); //NewSession.ID is autopopulated by DB 

    CleanSessions(ClientID); //Async method which I want to execute later 

    return NewSession.ID; 
} 

private async void CleanSessions(int ClientID) 
{ 
    //Asynchronously get expired sessions from DB based on ClientID and mark them for removal 
    await DB.SaveChangesAsync(); 
} 

मैंने टास्क.रुन() और समांतर। इन्वोक() के संयोजन सहित विभिन्न चीजों का एक गुच्छा करने की कोशिश की लेकिन स्वच्छ सत्र कभी नहीं बुलाया जाता है। मैं पृष्ठभूमि कार्य शेड्यूलिंग कैसे प्राप्त करूं?

+0

उस पर आधारित, 'SaveSangesAsync' समाप्त होने पर' क्लीनसेशंस 'प्रारंभ * होना चाहिए। यह शायद 'टास्क' और जाल त्रुटियों आदि के लिए 'प्रतीक्षा' कर सकता है - लेकिन इसे वहां से "जैसा है" काम करना चाहिए, मैं वहां देख सकता हूं –

+0

एक नोट: आपको अपने तरीकों के लिए * कभी भी * async void' का उपयोग नहीं करना चाहिए, शीर्ष-स्तरीय ईवेंट हैंडलर को छोड़कर। –

+0

@MarcGravell: एएसपी.NET प्रतिक्रिया भेजने से पहले सभी 'async शून्य' विधियों को पूरा करने की प्रतीक्षा करेगा। ओप आग और भूलना चाहता है। –

उत्तर

12

अनुरोध के बिना एएसपी.नेट में चल रहे कार्यों की अनुशंसा नहीं की जाती है। It's dangerous.

कहा कि, बदल CleanSessionsTask वापस जाने के लिए और आप इसे इस तरह से कर सकते हैं:

Task.Run(() => CleanSessions()); 

आपके मामले में, मुझे लगता है कि यह ठीक हो सकता है, वहाँ कोई दीर्घकालिक समस्या है क्योंकि यदि CleanSessions नहीं करता ' निष्पादित करने के बीच में निष्पादित या समाप्त हो जाता है (जो रीसाइक्लिंग के कारण एएसपी.नेट में हो सकता है)। आप ASP.NET आप प्रगति में कुछ काम है कि एक अनुरोध के साथ संबद्ध नहीं है कि सूचित करना चाहते हैं, तो आप BackgroundTaskManager from my blog इस तरह उपयोग कर सकते हैं:

BackgroundTaskManager.Run(() => CleanSessions()); 
+1

याद आया यह वही है जो मैं ढूंढ रहा था, धन्यवाद। मैं वास्तव में पहले से ही यह कोशिश कर चुका था लेकिन मेरे क्लीनसेशंस() विधि में एक बग था जो अपवाद पैदा कर रहा था, और क्योंकि अनुरोध के बिना विधि निष्पादित की जा रही है अपवाद नहीं पकड़ा जा रहा था। यह मुझे इंप्रेशन दे रहा था कि विधि बिल्कुल नहीं बुला रही थी! तो इस चाल का उपयोग करने वाले किसी भी व्यक्ति को यह नोट, इस उत्तर में दिए गए लिंक को पढ़ना सुनिश्चित करें और सुनिश्चित करें कि आप वास्तव में समझते हैं कि यह "खतरनाक" क्यों है। – user1084447

+0

लगभग 4 साल बाद कैसे? शायद एक अद्यतन? 2014 से आपका ब्लॉग अपडेट नहीं किया गया है, कोई नई अंतर्दृष्टि? – CularBytes

+0

@CularBytes: नहीं; एएसपी.नेट अभी भी वैसे ही काम करता है, और यह उत्तर अभी भी पूरी तरह मान्य है। 'BackgroundTaskManager' एएसपी.NET कोर पर काम नहीं करेगा, लेकिन आप' IHostedService' का उपयोग करके या 'IRegisteredObject' के बजाय' IAplicationLifetime' का उपयोग करके वही कर सकते हैं। –

0

के रूप में उल्लेख किया गया है, तुम क्या करने की कोशिश कर रहे हैं, तो कुछ "आग और भूल जाओ", लेकिन एएसपी.नेट के अंदर - तो आप ConfigureAwait पर देखना चाहेंगे; सिंक-संदर्भ को अनदेखा करने के लिए आप इसे await के हिस्से के रूप में उपयोग कर सकते हैं। यह सिंक-संदर्भ है जो इसे एएसपी.NET निष्पादन पाइपलाइन में वापस जोड़ता है, लेकिन यदि यह आवश्यक नहीं है तो आप इससे बच सकते हैं। उदाहरण के लिए:

public async Task<Guid> LogIn(string UserName, string Password) 
{ 
    //Asynchronously get ClientID from DB using UserName and Password 

    Session NewSession = new Session() 
    { 
     ClientID = ClientID, 
     TimeStamp = DateTime.Now 
    }; 
    DB.Sessions.Add(NewSession); 
    await DB.SaveChangesAsync().ConfigureAwait(false); //NewSession.ID is autopopulated by DB 

    await CleanSessions(ClientID).ConfigureAwait(false); //Async method which I want to execute later 

    return NewSession.ID; 
} 
// simplified: no need for this to be full "async" 
private Task CleanSessions(int ClientID) 
{ 
    //Asynchronously get expired sessions from DB based on ClientID 
    return DB.SaveChangesAsync(); 
} 
+1

इस समाधान में सबसे अच्छा त्रुटि हैंडलिंग ('क्लीनसेशंस' पर 'प्रतीक्षा' का उपयोग करके), लेकिन प्रतिक्रिया "प्रारंभिक" नहीं लौटाती है; 'क्लीनसेशंस' खत्म होने के बाद प्रतिक्रिया भेजी जाएगी। –

+1

आह, हाँ - भले ही * इस कोड * ने ConfigureAwait का उपयोग किया है, प्रतिक्रिया स्पष्ट रूप से तब तक नहीं भेजी जा सकती जब तक कि "प्रतीक्षा" समाप्त नहीं हो जाती। तो यदि आप कल्पना करते हैं कि * कॉलिंग * कोड इस कार्य का इंतजार कर रहा है, तो यह एएसपी.NET सिंक संदर्भ में होगा। –

+0

हाँ मैंने यह कोशिश की, यह अभी भी जारी रखने से पहले CleanSessions() का इंतजार कर रहा है। यह पूरा नहीं करता है जो मैं करने की कोशिश कर रहा हूं। – user1084447

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