मेरे पास पुनर्प्रयासों के साथ तुल्यकालिक संदर्भ में अतुल्यकालिक कार्यों को निष्पादित करने के लिए एक सामान्य विधि है।

public static T RunWithRetries<T>(Task<T> task)
{
   while(...) // 3 attempts
   {
       try 
       {
          task.GetAwaiter().GetResult();
       }
       catch 
       {
         // sleep & retry later in case of some exceptions, for example 429
       }
   }
}

फिर मैं इसे इस तरह चलाने के लिए एसिंक्रोनस एपीआई से किसी भी विधि को पास कर रहा हूं।

SyncHelper.RunWithRetries(externalAPI.UploadAsync(fileRequest, fileStream));

समस्या यह है कि यह तब तक काम करता है जब तक अनुरोध के दौरान कोई अपवाद न हो और हमें पुनः प्रयास करने की आवश्यकता हो। यदि कोई त्रुटि होती है, तो बाद के सभी पुन: प्रयास भी उसी अपवाद को फेंक रहे हैं। तो, मेरे प्रश्न हैं

  1. क्या यह फाइलस्ट्रीम ऑब्जेक्ट के कारण हो रहा है? यह प्रयोग कथन में है, इसलिए इसे निश्चित रूप से निपटाया नहीं जा रहा है। क्या पहले अपलोड प्रयास के बाद स्ट्रीम की स्थिति एक समस्या हो सकती है?
  2. क्या यह सामान्य है कि एक ही कार्य वस्तु का पुन: प्रयास किया जा रहा है? क्या मुझे अपने काम करने के तरीके को कुछ बेहतर करने के लिए बदलना चाहिए?
3
Gab 26 नवम्बर 2021, 13:10
1
सबसे पहले, GetAwaiter().GetResult() का उपयोग न करें, बस इसे await करें और इसे async करें, अन्यथा आपको अन्य समस्याएं होने वाली हैं। दूसरा, मैं पोली पर एक नज़र डालने का सुझाव दूंगा, यह एक पुस्तकालय है जो सभी पुनः प्रयास तर्क करता है आप यहां हासिल करने की कोशिश कर रहे हैं।
 – 
DavidG
26 नवम्बर 2021, 13:15
प्रोजेक्ट आर्किटेक्चर मुझे दुर्भाग्य से async/प्रतीक्षा का उपयोग करने की अनुमति नहीं देता है। उसके लिए बहुत बड़ी रिफैक्टरिंग की जरूरत है। पोली के बारे में - मैं वास्तव में इसे यहां सरल बनाना चाहता हूं और यदि संभव हो तो इसे बाहरी उपकरणों के बिना काम करना चाहता हूं।
 – 
Gab
26 नवम्बर 2021, 13:18
3
अपने प्रश्नों को प्रतिबिंबित करते हुए: 1) यदि आपने डाउनस्ट्रीम सिस्टम को अनुरोध जारी करने के लिए fileStream पढ़ लिया है तो आपको एक नया अनुरोध पुनः प्रयास करने से पहले शुरुआत में वापस जाना होगा। 2) यदि कोई कार्य पहले ही समाप्त हो चुका है तो उसका परिणाम पुनर्प्राप्त करने से कार्य फिर से निष्पादित नहीं होगा, यह केवल परिणाम देता है। इसलिए, एक Func<Task<T>> प्राप्त करना उचित होगा, जिसे कई बार कॉल किया जा सकता है। RunWithRetries(() => externalAPI.UploadAsync...
 – 
Peter Csala
26 नवम्बर 2021, 13:39
1
मैं अब एक Func पास करने और वहां इसका उपयोग करने के आपके दृष्टिकोण की कोशिश कर रहा हूं। मैं भी पारित समारोह के अंदर धारा बनाने की कोशिश कर रहा हूँ। मुझे लगता है कि आप अपनी टिप्पणी को उत्तर में बदल सकते हैं, इसलिए अगर यह काम करेगा तो मैं इसे स्वीकार कर सकता हूं।
 – 
Gab
26 नवम्बर 2021, 14:30

1 उत्तर

सबसे बढ़िया उत्तर

क्या यह fileStream ऑब्जेक्ट के कारण हो रहा है? यह प्रयोग कथन में है, इसलिए इसे निश्चित रूप से निपटाया नहीं जा रहा है। क्या पहले अपलोड प्रयास के बाद स्ट्रीम की स्थिति एक समस्या हो सकती है?

हाँ, यह आपकी समस्याओं में से एक है। जब भी कोई स्ट्रीम पढ़ी जाती है तो उसका Position स्वतः 0 पर रीसेट नहीं होता है। यदि आप इसे फिर से पढ़ने का प्रयास करते हैं तो यह कुछ भी नहीं पढ़ेगा क्योंकि स्थिति धारा के अंत में है।

इसलिए, आपको या तो हर बार एक नई स्ट्रीम बनानी होगी या स्ट्रीम को शुरुआत में वापस करना होगा.

क्या यह सामान्य है कि एक ही कार्य वस्तु का पुन: प्रयास किया जा रहा है? क्या मुझे अपने काम करने के तरीके को कुछ बेहतर करने के लिए बदलना चाहिए?

जब भी कोई कार्य समाप्त हो जाता है (या तो किसी विशेष परिणाम के साथ या अपवाद के साथ) तो फिर से-await-इंग या उसके Result को पुनः प्राप्त करने से पुन: निष्पादन ट्रिगर नहीं होगा। यह मूल्य या अपवाद को सरल रूप से वापस कर देगा।

इसलिए, आपको प्रत्येक पुन: प्रयास के लिए एक नया कार्य बनाना होगा। ऐसा करने के लिए आप अपने RunWithRetries में एक Func<Task<T>> का अनुमान लगा सकते हैं

public static T RunWithRetries<T>(Func<Task<T>> issueRequest)
{
    ...
    issueRequest().GetAwaiter().GetResult();

}

फोन करने वाले की तरफ से यह इस तरह दिखेगा:

RunWithRetries(() => externalAPI.UploadAsync(fileRequest, new FileStream(...)));
//or
RunWithRetries(() => { fileStream.Position = 0; externalAPI.UploadAsync(fileRequest, fileStream); });
2
Peter Csala 26 नवम्बर 2021, 14:44
1
मैंने पास किए गए फ़ंक्शन में स्ट्रीम को फिर से बनाया और यह काम किया (लेकिन मुझे इसे निपटाने के लिए एसिंक-प्रतीक्षा का उपयोग नहीं करना पड़ा)। RunWithRetries (async () => का उपयोग कर (फाइलस्ट्रीम फाइलस्ट्रीम =...) {बाहरी एपीआई की प्रतीक्षा करें। अपलोडएसिंक (फाइल रिक्वेस्ट, फाइलस्ट्रीम);});
 – 
Gab
26 नवम्बर 2021, 15:13