C #: शेष अनुरोधों को पूरा किए बिना थ्रेड गर्भपात

Aug 18 2020

मैंने एक अनुसूचक को लागू किया है जो तीसरे पक्ष के समापन बिंदु के लिए अनुरोध भेजता है। प्रतिक्रिया प्राप्त करने के बाद, मेरे स्थानीय डेटाबेस को प्रतिक्रिया के साथ अद्यतन किया जाता है। वर्तमान में, मैं 50K से अधिक अनुरोध (प्रत्येक 10 मिनट में 1K अनुरोध) भेज रहा हूं और प्रतिक्रिया की प्रक्रिया कर रहा हूं। मुद्दा कभी-कभी तीसरे पक्ष का सर्वर प्रतिक्रिया नहीं देता है या अनुरोध समय समाप्त नहीं होता है। इस मामले में मुझे एक अपवाद मिलता है और शेष अनुरोधों को संसाधित किए बिना धागा निरस्त कर दिया जाता है। मुझे धागा को निरस्त करने और अगले रिकॉर्ड के साथ आगे बढ़ने की आवश्यकता नहीं है ताकि मिस्ड आउट रिकॉर्ड दूसरे बैच में संसाधित हो। यहाँ कोड का उपयोग कर रहा हूँ।

public class ScheduledAPIJob : IJob
{
    public Task Execute(IJobExecutionContext context)
    {
        Task taskAPI = Task.Factory.StartNew(() => ProcessAPI());
        return taskAPI;
    }
    void ProcessAPI()
    {
        //Error logging object
        SchedulerLogWriter lw = new SchedulerLogWriter("Logs\\Scheduler");

        List<WeatherData> list = new List<WeatherData>();

        APIQueueBAL objBal = new APIQueueBAL();

        //List of endpoints to hit.
        var APIQueue = objBal.QueuedAPIs();

        foreach (var item in APIQueue)
        {
            try
            {
                var endpoint = item.FunctionParameters;
                HttpRequestHelper objRequestHelper = new HttpRequestHelper();
                
                //Response from API
                var response = objRequestHelper.GetAPIResponse(endpoint);
                
                ////Update local database.
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    list = JsonConvert.DeserializeObject<List<WeatherData>>(response.Content.ReadAsStringAsync().Result);
                    objBal.ProcessWeatherData(item, list);
                }
            }
            catch (Exception ex)
            {
                lw.WriteLog(ex.Message);
                lw.WriteLog(Convert.ToString(ex.InnerException));
                lw.WriteLog(ex.StackTrace);
            }
        }
    }
}

public class HttpRequestHelper
{
    public HttpResponseMessage GetAPIResponse(string apiEndpoint)
    {
        using (var client = new HttpClient())
        {
            var getTask = client.GetAsync(apiEndpoint);
            getTask.Wait();
            return getTask.Result;
        }
    }
}

जवाब

aepot Aug 18 2020 at 14:38

HttpClientप्रलेखन के अनुसार :

HttpClient प्रति-उपयोग के बजाय, एक बार प्रति एप्लिकेशन तुरंत इंस्टेंट किए जाने का इरादा है।

HttpClientअनुरोध के अनुसार उदाहरण सॉकेट थकावट का कारण बन सकता है जो नए अनुरोध भेजने के लिए संभव नहीं है।

कभी-कभी तीसरा पक्ष सर्वर प्रतिक्रिया नहीं देता है

शायद 3-पार्टी सर्वर ठीक है, लेकिन आपकी सॉकेट्स नहीं हैं। यह ThreadAbortExceptionकुछ नए अनुरोधों पर भी भेजा जा सकता है, खासकर यदि आप अनुरोध को सिंक्रोनाइज़ कर रहे हैं। getTask.Wait()यह सिंक-ओवर-एस्किंक कॉल है जो यहां अनुशंसित नहीं है और आवश्यक नहीं है।

उपयोग करने के लिए इस अद्यतन कोड पर विचार करें async/await

public class ScheduledAPIJob : IJob
{
    public Task Execute(IJobExecutionContext context)
    {
        return ProcessAPI();
    }
    private async Task ProcessAPI()
    {
        //Error logging object
        SchedulerLogWriter lw = new SchedulerLogWriter("Logs\\Scheduler");

        APIQueueBAL objBal = new APIQueueBAL();

        //List of endpoints to hit.
        var APIQueue = objBal.QueuedAPIs();

        foreach (var item in APIQueue)
        {
            try
            {
                string endpoint = item.FunctionParameters;

                //Response from API
                List<WeatherData> list = await HttpRequestHelper.GetAPIResponseAsync<List<WeatherData>>(endpoint);
                objBal.ProcessWeatherData(item, list);
            }
            catch (Exception ex)
            {
                lw.WriteLog(ex.Message);
                lw.WriteLog(Convert.ToString(ex.InnerException));
                lw.WriteLog(ex.StackTrace);
            }
        }
    }
}

public static class HttpRequestHelper
{
    private static readonly HttpClient client = new HttpClient();

    public static async Task<T> GetAPIResponseAsync<T>(string apiEndpoint)
    {
        using (HttpResponseMessage response = await client.GetAsync(apiEndpoint, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
        {
            response.EnsureSuccessStatusCode(); // throws if not success
            string json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            return JsonConvert.DeserializeObject<T>(json);
        }
    }
}

नोट: यदि आप उपयोग कर रहे हैं .Resultया .GetAwaiter().GetResult()पूरा नहीं किया है Task, तो इसका मतलब है कि कुछ गलत हो गया है और आपके सामने बुरा व्यवहार है जो संभवतः गतिरोध का कारण है।

उपरोक्त कोड को समवर्ती अनुरोधों में सुधार किया जा सकता है जैसे कि एक बार में सभी भेजें या एक बार में अधिकतम सक्रिय सीमा के साथ संभालें। लेकिन पहले यह सुनिश्चित करना बेहतर है कि उपरोक्त कोड काम करता है।