क्यों तुल्यकालिक कनेक्शन के लिए HttpClient का उपयोग करें


188

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

अगर कोई किसी भी प्रकाश को बहा सकता है तो मैं इसकी बहुत सराहना करूंगा। मैं इसके लिए नई तकनीक का उपयोग करने के लिए एक नहीं हूं।


3
मुझे आपको बताने से नफरत है, लेकिन विंडोज़ नेटवर्क आंतरिक रूप से कैसे काम करता है (उर्फ पूर्णता पोर्ट) के कारण HTTP पर कॉल कभी भी विशुद्ध रूप से तुल्यकालिक नहीं होता है।
टॉमटॉम


जवाबों:


372

लेकिन मैं जो कर रहा हूं वह विशुद्ध रूप से समकालिक है

आप HttpClientसमकालिक अनुरोधों के लिए उपयोग कर सकते हैं:

using (var client = new HttpClient())
{
    var response = client.GetAsync("http://google.com").Result;

    if (response.IsSuccessStatusCode)
    {
        var responseContent = response.Content; 

        // by calling .Result you are synchronously reading the result
        string responseString = responseContent.ReadAsStringAsync().Result;

        Console.WriteLine(responseString);
    }
}

जहां तक ​​आपको HttpClientओवर WebRequestका उपयोग क्यों करना चाहिए , इसका संबंध है, ठीक है, HttpClientब्लॉक पर नया बच्चा है और इसमें पुराने ग्राहक पर सुधार शामिल हो सकते हैं।


27
क्या एसिंक्स विधियों का आपका तुल्यकालिक उपयोग संभावित रूप से आपके UI थ्रेड को ब्लॉक नहीं करेगा? string responseString = Task.Run(() => responseContent.ReadAsStringAsync()).Result;यदि आप इस समकालिक बनाना चाहिए, तो आप इसके बजाय कुछ विचार करना चाहते हैं।
पृथ्वी

13
@earthling, हां, थ्रेडपूल Task.Runसे कार्य को आमंत्रित करता है, लेकिन आप इस .Resultपर कॉल कर रहे हैं इससे होने वाले सभी लाभों को मारना और उस थ्रेड को अवरुद्ध करना जिसमें आपने इसे कॉल किया था .Result(जो आमतौर पर मुख्य UI थ्रेड होता है)।
डारिन दिमित्रोव

35
इस पोस्ट ( blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx ) के अनुसार इस .Resultतरह से कॉल करना थ्रेडपूल को समाप्त कर सकता है और गतिरोध पैदा कर सकता है।
पीट गराफानो

16
यह कोड हमेशा गतिरोध में रहेगा यदि मुख्य UI थ्रेड पर बनाए गए कार्य के भीतर निष्पादित किया गया होnew TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()
Wim Coenen

23
तो, मैं UI थ्रेड से HttpClient को सिंक्रोनाइज़ कैसे करूं? चलो कहते हैं कि मैं जानबूझ कर यूआई धागा (या मैं एक सांत्वना अनुप्रयोग लिख रहा हूँ) जब तक मैं HTTP प्रतिसाद मिलता है ... तो, अगर प्रतीक्षा (), परिणाम (), आदि गतिरोध पैदा कर सकता है, क्या इस बात के लिए निश्चित समाधान है ब्लॉक करना चाहते हैं के बिना गतिरोध का खतरा और WebClient जैसी अन्य कक्षाओं का उपयोग किए बिना ?
Dexter

26

मैं डोनी वी। जवाब और जोश की पुन: पुनरावृति करूँगा

"केवल एक ही कारण है कि मैं async संस्करण का उपयोग नहीं करेगा अगर मैं .NET के पुराने संस्करण का समर्थन करने की कोशिश कर रहा था जो पहले से ही async समर्थन में निर्मित नहीं है।"

(और प्रतिष्ठा अगर मेरे पास थी)

मैं पिछली बार याद नहीं कर सकता अगर कभी भी, मैं इस तथ्य के लिए आभारी था कि HttpWebRequest ने स्टेटस कोड> = 400 के लिए अपवादों को फेंक दिया। इन मुद्दों को हल करने के लिए आपको अपवादों को तुरंत पकड़ने की जरूरत है, और उन्हें कुछ गैर-अपवाद प्रतिक्रिया तंत्रों पर मैप करें। अपने कोड में ... अपने आप में उबाऊ, थकाऊ और त्रुटि प्रवण। चाहे वह एक डेटाबेस के साथ संवाद कर रहा हो, या एक bespoke वेब प्रॉक्सी को लागू कर रहा हो, इसका 'लगभग' हमेशा वांछनीय है कि Http ड्राइवर सिर्फ आपके आवेदन कोड को बताए कि क्या लौटाया गया था, और यह कैसे व्यवहार करना है यह तय करने के लिए आप पर छोड़ दें।

इसलिए HttpClient बेहतर है।


1
मुझे आश्चर्य हुआ कि HttpClientखुद एक रैपर है HttpWebRequest(जो वास्तव में, आंतरिक रूप से उन WebExceptionवस्तुओं को पकड़ता है और आपके लिए रूपांतरण करता है HttpResponseMessage)। मैंने सोचा होगा कि स्क्रैच से पूरी तरह से एक नया क्लाइंट बनाना आसान होगा।
दाई

4
बहुत सारे अच्छे कारण हैं जैसे कि बहुत कम-स्तरीय http कॉल के लिए अपने पूरे कोडबेस को फिर से लिखना नहीं चाहते हैं, जो कि प्रदर्शन को महत्वपूर्ण नहीं है (लेकिन एक लाख स्थानों पर async शुरू करेगा)।
फ्रेंकबॉय

.Net कोर 2 में यदि आप डायनामिकएक्सप्रेशनप्रैसर के साथ किसी अभिव्यक्ति का डायनामिक रूप से मूल्यांकन करना चाहते हैं, तो यह async का उपयोग करना संभव नहीं हो सकता है; संपत्ति अनुक्रमणिका async का उपयोग नहीं कर सकते हैं; मेरी स्थिति में मैं गतिशील "GetDefaultWelcomeMessage [\" InitialMessage \ "]" जहां इस पद्धति का एक HttpCall और सूचकांक वाक्य रचना विधि वाक्य रचना "Util.GetDefaultWelcomeMessage (\" InitialMessage \ ")" बेहतर है बनाता है इस तरह की स्ट्रिंग मूल्यांकन करने की जरूरत
यूजेन

7

यदि आप एक कक्षा पुस्तकालय का निर्माण कर रहे हैं, तो शायद आपके पुस्तकालय के उपयोगकर्ता आपके पुस्तकालय का उपयोग अतुल्यकालिक रूप से करना चाहेंगे। मुझे लगता है कि यही सबसे बड़ा कारण है।

आपको यह भी पता नहीं है कि आपकी लाइब्रेरी का उपयोग कैसे किया जाएगा। शायद उपयोगकर्ता बहुत सारे और बहुत सारे अनुरोधों को संसाधित कर रहे होंगे, और अतुल्यकालिक रूप से ऐसा करने से इसे तेजी से और अधिक कुशल प्रदर्शन करने में मदद मिलेगी।

यदि आप ऐसा सरलता से कर सकते हैं, तो कोशिश करें कि अपने पुस्तकालय के उपयोगकर्ताओं पर बोझ न डालें, क्योंकि जब आप उनके लिए इसकी देखभाल कर सकते हैं तो प्रवाह को अतुल्यकालिक बनाने की कोशिश कर रहे हैं।

एकमात्र कारण जो मैं async संस्करण का उपयोग नहीं करता, वह यह है कि मैं .NET के पुराने संस्करण का समर्थन करने की कोशिश कर रहा था जो कि पहले से ही async समर्थन में निर्मित नहीं है।


मैं देखता हूं, इसलिए कक्षा की लाइब्रेरी को अतुल्यकालिक बना दें, और सिस्टम के उपयोगकर्ताओं को यह तय करने की अनुमति दें कि क्या वह एसिंक्रोनस का उपयोग करें, या प्रतीक्षा का उपयोग करें और इसे समान रूप से उपयोग करें?
केचप

erm, कॉल करने वाले पर नियंत्रण वापस करके कुछ कॉलों को अतुल्यकालिक बनाने में मदद करता है।
जोश स्मेटन

6

मेरे मामले में स्वीकृत जवाब से काम नहीं चला। मैं एक एमवीसी एप्लिकेशन से एपीआई को कॉल कर रहा था जिसमें कोई एसिंक्स कार्रवाई नहीं थी।

यह है कि मैं इसे कैसे काम करने में कामयाब रहा:

private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public static T RunSync<T>(Func<Task<T>> func)
    {           
        CultureInfo cultureUi = CultureInfo.CurrentUICulture;
        CultureInfo culture = CultureInfo.CurrentCulture;
        return _myTaskFactory.StartNew<Task<T>>(delegate
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = cultureUi;
            return func();
        }).Unwrap<T>().GetAwaiter().GetResult();
    }

फिर मैंने उसे इस तरह बुलाया:

Helper.RunSync(new Func<Task<ReturnTypeGoesHere>>(async () => await AsyncCallGoesHere(myparameter)));

1
Thx @Darkonekt ... यह मेरे लिए पूरी तरह से काम करता है। केवल HttpClient.SendAsync (...)। परिणाम AspNet हैंडलर (.ASHX) के अंदर कभी काम नहीं करता है।
राफेल काजुओ सातो सिमियो

3
public static class AsyncHelper  
{
    private static readonly TaskFactory _taskFactory = new
        TaskFactory(CancellationToken.None,
                    TaskCreationOptions.None,
                    TaskContinuationOptions.None,
                    TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();

    public static void RunSync(Func<Task> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();
}

फिर

AsyncHelper.RunSync(() => DoAsyncStuff());

यदि आप उस वर्ग को अपने async विधि का उपयोग करते हैं तो पैरामीटर के रूप में आप async विधियों को सुरक्षित तरीके से सिंक विधियों से कॉल कर सकते हैं।

इसे यहाँ समझाया गया है: https://cpratt.co/async-tips-tricks/


-1

सभी उत्तर HttpClientप्रश्न के वास्तविक उत्तर देने के बजाय समकालिक रूप से उपयोग करने पर ध्यान केंद्रित करते हैं ।

HttpClientयह एक साधारण अनुरोध / प्रतिक्रिया हैंडलर से अधिक है इसलिए यह विभिन्न नेटवर्क की कुछ ख़ासियतों से निपट सकता है। मेरे मामले में एनटीएलएम प्रॉक्सी के साथ काम करना, जिसमें बातचीत की आवश्यकता होती है, प्रमाणीकरण के लिए क्लाइंट और प्रॉक्सी सर्वर के बीच टोकन और क्रेडेंशियल्स के साथ कई अनुरोध / प्रतिक्रियाएं भेजना। HttpClient(उपयोग करते हुए HttpClientHandler) ऐसा लगता है कि अंतर्निहित तंत्र है जो एक विधि कॉल के साथ प्रॉक्सी से परे संसाधन लौटाता है।


आपका उत्तर यह नहीं बताता है कि HttpClient का उपयोग कैसे किया जाए।
user275801

@ user275801 यह गूंगा टिप्पणी है। ऐसा किसी ने नहीं पूछा। यह डिफ़ॉल्ट रूप से अतुल्यकालिक है।
बिज़नीटाइम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.