आप एक async कार्रवाई प्रतिनिधि विधि को कैसे लागू करते हैं?


132

थोड़ी पृष्ठभूमि की जानकारी।

मैं वेब एपीआई स्टैक सीख रहा हूं और मैं सफलता और त्रुटिकोड जैसे मापदंडों के साथ "परिणाम" ऑब्जेक्ट के रूप में सभी डेटा को एनकोड करने की कोशिश कर रहा हूं।

हालांकि, अलग-अलग विधियां अलग-अलग परिणाम और त्रुटि कोड उत्पन्न करेंगी, लेकिन परिणाम वस्तु को आम तौर पर उसी तरह त्वरित किया जाएगा।

कुछ समय बचाने के लिए और C # में async / प्रतीक्षारत क्षमताओं के बारे में और जानने के लिए, मैं अपने वेब एपी कार्यों की सभी विधि निकायों को एक एसिंक्रोनस एक्शन डेलिगेट में लपेटने की कोशिश कर रहा हूं, लेकिन थोड़ा बहुत रोड़ा अटक गया ...

निम्नलिखित वर्गों को देखते हुए:

public class Result
{
    public bool Success { get; set; }
    public List<int> ErrorCodes{ get; set; }
}

public async Task<Result> GetResultAsync()
{
    return await DoSomethingAsync<Result>(result =>
    {
        // Do something here
        result.Success = true;

        if (SomethingIsTrue)
        {
            result.ErrorCodes.Add(404);
            result.Success = false;
        }
    }
}

मैं एक विधि लिखना चाहता हूं जो एक परिणाम ऑब्जेक्ट पर एक क्रिया करता है और इसे वापस करता है। आम तौर पर तुल्यकालिक तरीकों के माध्यम से यह होगा

public T DoSomethingAsync<T>(Action<T> resultBody) where T : Result, new()
{
    T result = new T();
    resultBody(result);
    return result;
}

लेकिन मैं इस पद्धति को एसिंक्रोनस / वेट का उपयोग करके एक अतुल्यकालिक विधि में कैसे बदलूं?

यही मैंने कोशिश की है:

public async Task<T> DoSomethingAsync<T>(Action<T, Task> resultBody) 
    where T: Result, new()
{
    // But I don't know what do do from here.
    // What do I await?
}

1
यदि आप newऊपर हैं T, तो आपकी पद्धति को अतुल्यकालिक होने की आवश्यकता क्यों है? अतुल्यकालिक एपीआई का उपयोग करके कोड में AFAIK , आपको केवल asyncउन अन्य तरीकों से नेस का प्रचार करने की आवश्यकता है जो आप उपयोग करते हैं।
मिलीमोसे

क्षमा करें, मैं अभी भी इसके लिए काफी नया हूं, आपके कहने का क्या मतलब है जब आपको केवल प्रचार करने की आवश्यकता है, और टी-आई को इसके साथ क्या करना है?
एल्बिन अंके

मुझे लगता है कि मुझे यह समझ में आ गया, धन्यवाद मिलीमोसे आपने मुझे सोचने के लिए कुछ दिया।
एल्बिन अंके

1
आप भी इस async करने की कोशिश क्यों कर रहे हैं? कार्यों में सिंक्रोनस कोड लपेटकर (जैसे आप करने की कोशिश कर रहे हैं) वेबरवेयर स्थितियों में अधिक बार ऐसा नहीं होता है कि यह केवल सिंक्रोनाइज़ करने की तुलना में धीमा है।
स्कॉट चेम्बरलेन

1
@AlbinAnke द्वारा "प्रचार" मेरा मतलब है कि अगर आप की तरह एक नेट विधि कॉल कर रहे हैं Stream.ReadAsync()एक विधि में, उस विधि में ही अतुल्यकालिक होना चाहिए, और वापसी एक Task<T>जहां Tहै जो आप वापस आ गए होता विधि तुल्यकालिक थे। यह विचार यह है कि इस तरह से, आपके विधि का प्रत्येक कॉलर तब "असिंक्रोनसली प्रतीक्षा" कर सकता है (मुझे नहीं पता कि इसके लिए एक अच्छा शब्द क्या है) अंतर्निहित Stream.ReadAsync()को पूरा करने के लिए। इसके लिए एक रूपक आप उपयोग कर सकते हैं कि async "संक्रामक" है, और निम्न-स्तर के अंतर्निहित I / O से दूसरे कोड में फैलता है, जिनके परिणाम I / O के उन लोगों पर निर्भर करते हैं।
मिलीमोसे

जवाबों:


307

asyncके बराबर Action<T>है Func<T, Task>, इसलिए मेरा मानना है कि यह आपके लिए क्या देख रहे हैं:

public async Task<T> DoSomethingAsync<T>(Func<T, Task> resultBody)
    where T : Result, new()
{
  T result = new T();
  await resultBody(result);
  return result;
}

@ स्टेफेन स्पष्ट रूप से मैं एमवीवीएम लिगथ मैसेंजर में कुछ समान लागू करने की कोशिश कर रहा हूं, क्या मैं उसी तरह लागू कर सकता हूं?
जुआन पाब्लो गोमेज़

@JuanPabloGomez: मैं उनके प्रकार के संदेश से परिचित नहीं हूं, लेकिन मैं यह नहीं देखता कि यह काम क्यों नहीं करेगा।
स्टीफन क्लीयर

1
ये अद्भुत है! मैंने सोचा था कि यह एक async कार्रवाई करने के लिए संभव नहीं होगा, और पहले से ही यह एक भाषा दोष माना जाता है। मैंने फंक का उपयोग करने के बारे में नहीं सोचा था। धन्यवाद।
नोएल विडमेर

2
@DFSFOT: एक voidविधि के async समतुल्य Taskविधि है; इस प्रकार, async समतुल्य Actionहै Func<Task>, और async समतुल्य Action<T>है Func<T, Task>। अधिक जानकारी यहाँ
स्टीफन क्लीयर

1
@DFSFOT: Taskजब वापस रिटर्न वैल्यू नहीं है तो एक एसिंक्स पद्धति वापस आनी चाहिए । यदि यह asyncकीवर्ड का उपयोग करता है , तो वास्तविक Taskउदाहरण एक राज्य मशीन द्वारा बनाया जाएगा, न कि सीधे कार्य।
स्टीफन क्ली

-11

इसलिए मेरा मानना ​​है कि इसे लागू करने का तरीका यह है:

public Task<T> DoSomethingAsync<T>(Action<T> resultBody) where T : Result, new()
{
    return Task<T>.Factory.StartNew(() =>
    {
        T result = new T();
        resultBody(result);
        return result;
    });
}

7
आपको ASP.NET पर Task.Run(और भी बहुत कुछ StartNew) बचना चाहिए ।
स्टीफन क्लीयर

ऐसा करने का एक बेहतर तरीका क्या है?
एल्बिन एंक

मैंने एक उत्तर पोस्ट किया, और @ svick के उत्तर को भी उकेरा। वे दोनों अच्छे उत्तर हैं।
स्टीफन क्ली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.