मेरे पास कुछ लाइब्रेरी (सॉकेट नेटवर्किंग) कोड है जो Task
अनुरोधों के आधार पर लंबित प्रतिक्रियाओं के लिए एक- आधारित एपीआई प्रदान करता है TaskCompletionSource<T>
। हालांकि, टीपीएल में एक झुंझलाहट है कि यह तुल्यकालिक निरंतरता को रोकने के लिए असंभव प्रतीत होता है। मैं ऐसा करने में सक्षम होना चाहूंगा :
- यह बताएं
TaskCompletionSource<T>
कि कॉल करने वालों के साथ संलग्न करने की अनुमति नहीं देनी चाहिएTaskContinuationOptions.ExecuteSynchronously
, या - परिणाम (
SetResult
/TrySetResult
) को एक तरह से सेट करें जो निर्दिष्ट करता है किTaskContinuationOptions.ExecuteSynchronously
इसे अनदेखा किया जाना चाहिए, इसके बजाय पूल का उपयोग करना चाहिए
विशेष रूप से, मेरे पास मुद्दा यह है कि आने वाले डेटा को एक समर्पित पाठक द्वारा संसाधित किया जा रहा है, और यदि कोई कॉलर TaskContinuationOptions.ExecuteSynchronously
उनके साथ संलग्न कर सकता है तो वह पाठक को रोक सकता है (जो कि उन्हें केवल इससे अधिक प्रभावित करता है)। पहले, मैंने इसके चारों ओर कुछ हैकरी द्वारा काम किया है जो पता लगाता है कि क्या कोई निरंतरता मौजूद है, और अगर वे इसे पूरा करने पर जोर देते हैं ThreadPool
, हालांकि यह महत्वपूर्ण प्रभाव पड़ता है यदि कॉलर ने अपनी कार्य कतार को संतृप्त किया है, क्योंकि पूरा होने पर कार्रवाई नहीं होगी। समयानुकूल ढंग से। यदि वे Task.Wait()
(या समान) उपयोग कर रहे हैं , तो वे अनिवार्य रूप से खुद को गतिरोध करेंगे। इसी तरह, यह इसलिए है कि पाठक श्रमिकों का उपयोग करने के बजाय एक समर्पित सूत्र पर है।
इसलिए; इससे पहले कि मैं कोशिश करूँ और टीपीएल टीम को नंगा करूँ: क्या मुझे एक विकल्प याद आ रहा है?
प्रमुख बिंदु:
- मैं नहीं चाहता कि बाहरी कॉलर्स मेरे धागे को हाईजैक करने में सक्षम हों
- मैं
ThreadPool
एक कार्यान्वयन के रूप में उपयोग नहीं कर सकता , क्योंकि पूल के संतृप्त होने पर इसे काम करने की आवश्यकता होती है
उत्पादन (उत्पादन समय के आधार पर अलग-अलग हो सकता है) के उदाहरण नीचे दिए गए हैं:
Continuation on: Main thread
Press [return]
Continuation on: Thread pool
समस्या यह है कि एक यादृच्छिक कॉलर "मेन थ्रेड" पर एक निरंतरता प्राप्त करने में कामयाब रहा। वास्तविक कोड में, यह प्राथमिक पाठक को बाधित करेगा; बुरी चीजें!
कोड:
using System;
using System.Threading;
using System.Threading.Tasks;
static class Program
{
static void Identify()
{
var thread = Thread.CurrentThread;
string name = thread.IsThreadPoolThread
? "Thread pool" : thread.Name;
if (string.IsNullOrEmpty(name))
name = "#" + thread.ManagedThreadId;
Console.WriteLine("Continuation on: " + name);
}
static void Main()
{
Thread.CurrentThread.Name = "Main thread";
var source = new TaskCompletionSource<int>();
var task = source.Task;
task.ContinueWith(delegate {
Identify();
});
task.ContinueWith(delegate {
Identify();
}, TaskContinuationOptions.ExecuteSynchronously);
source.TrySetResult(123);
Console.WriteLine("Press [return]");
Console.ReadLine();
}
}
TaskCompletionSource
अपने एपीआई के साथ सीधे कॉल को रोकने की कोशिश करूँगाContinueWith
, क्योंकि न तोTaskCompletionSource
, और न हीTask
उनसे विरासत के लिए अच्छी तरह से सूट नहीं करता।