2012-10-08 18 views
10

में बफरब्लॉक का उपयोग करने के लाभ मैं सोच रहा था कि क्या एक या कई एक्शनब्लॉक से जुड़े बफरब्लॉक का उपयोग करने से जुड़े लाभ हैं, थ्रॉटलिंग (बोल्ड कैपेसिटी का उपयोग करके) के अलावा, सीधे एक्शनब्लॉक (ओं) पर पोस्ट करने के बजाय लंबे समय तक थ्रॉटलिंग की आवश्यकता नहीं है)। डेटाफ्लो नेटवर्क

उत्तर

15

यदि आप एक ब्लॉक से कई अन्य लोगों को आइटम अग्रेषित करना चाहते हैं, तो आपको BufferBlock की आवश्यकता नहीं है।

लेकिन निश्चित रूप से ऐसे मामले हैं जहां यह उपयोगी है। उदाहरण के लिए, यदि आपके पास एक जटिल डेटाफ्लो नेटवर्क है, तो आप इसे छोटे उप-नेटवर्क से बनाना चाहते हैं, प्रत्येक व्यक्ति अपनी विधि में बनाया गया है। और ऐसा करने के लिए, आपको ब्लॉक के समूह का प्रतिनिधित्व करने के लिए कुछ तरीका चाहिए। यदि आपने उल्लेख किया है, तो विधि से उस एकल BufferBlock (शायद ITargetBlock) को वापस करना एक आसान समाधान होगा।

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

मुझे यकीन है कि कई अन्य उदाहरण हैं जहां आप BufferBlock का उपयोग कर सकते हैं। बेशक, अगर आपको अपने मामले में इसका इस्तेमाल करने का कोई कारण नहीं दिखता है, तो नहीं।

+0

मुझे लगता है कि BufferBlocks का उपयोग कर dataflow ब्लॉकों के बीच संवाद स्थापित करने की "स्वच्छ" तरीका है, लेकिन भूमि के ऊपर (यदि हो तो) इसके लायक BufferBlocks का उपयोग करने का है? – Dimitri

+1

यह आपके लिए तय करना है। अगर आपको लगता है कि यह आपके कोड क्लीनर बनाता है, तो इसे करें। इसमें कुछ ओवरहेड है, लेकिन मुझे लगता है कि यह ध्यान देने योग्य नहीं होना चाहिए, जब तक कि आप वास्तव में प्रदर्शन की परवाह नहीं करते। – svick

19

svick के उत्तर में जोड़ने के लिए, बफरब्लॉक का एक और लाभ है। यदि आपके पास एकाधिक आउटपुट लिंक वाले ब्लॉक हैं और उनके बीच संतुलन रखना चाहते हैं, तो आपको आउटपुट ब्लॉक को लालची में बदलना होगा और कतार को संभालने के लिए बफरब्लॉक जोड़ना होगा।

एक लिंक से उद्धृत किया गया है कि अब मर चुका:: मैं निम्न उदाहरण उपयोगी पाया

  • कुछ कोड ब्लॉक यह है का उपयोग कर BufferBlock करने के लिए डेटा पोस्ट करेंगे:

    यह हम क्या करने की योजना बना रहे है पोस्ट (टी टी) विधि।

  • यह बफरब्लॉक लिंकर टी का उपयोग करके 3 एक्शनब्लॉक उदाहरणों से जुड़ा हुआ है) बफरब्लॉक की विधि।

ध्यान दें, कि BufferBlock करता है सभी लक्ष्य ब्लॉकों यह जुड़ा हुआ है to.Instead यह only.Here हम जब एक लक्ष्य संसाधित करने में व्यस्त है कि उम्मीद कर रहे हैं एक लक्ष्य ब्लॉक करने के लिए ऐसा नहीं करता है के लिए इनपुट डेटा का नहीं हवाले प्रतियां अनुरोध। इसे दूसरे लक्ष्य को सौंप दिया जाएगा।अब चलो नीचे कोड का उल्लेख करते हैं:

static void Main(string[] args) 
    { 
     BufferBlock<int> bb = new BufferBlock<int>(); 
     ActionBlock<int> a1 = new ActionBlock<int>((a) => 
                { 
                 Thread.Sleep(100); 
                 Console.WriteLine("Action A1 executing with value {0}", a); 
                } 
               ); 

     ActionBlock<int> a2 = new ActionBlock<int>((a) => 
                { 
                 Thread.Sleep(50); 
                 Console.WriteLine("Action A2 executing with value {0}", a); 
                } 
               ); 
     ActionBlock<int> a3 = new ActionBlock<int>((a) => 
                { 
                 Thread.Sleep(50); 
                 Console.WriteLine("Action A3 executing with value {0}", a); 
                } 
               ); 
     bb.LinkTo(a1); 
     bb.LinkTo(a2); 
     bb.LinkTo(a3); 
     Task t = new Task(() => 
          { 
           int i = 0; 
           while (i < 10) 
           { 
            Thread.Sleep(50); 
            i++; 
            bb.Post(i); 
           } 
          } 
         ); 
     t.Start(); 
     Console.Read(); 
    } 

जब निष्पादित यह निम्नलिखित उत्पादन का उत्पादन:

  • कार्रवाई A1 मान के साथ क्रियान्वित 1
  • कार्रवाई A1 2
  • कार्रवाई A1 क्रियान्वित मूल्य के साथ क्रियान्वित मूल्य 3
  • एक्शन ए 1 निष्पादन मूल्य 4
  • एक्शन ए 1 निष्पादन मूल्य 5के साथ निष्पादन
  • कार्रवाई A1 मान के साथ क्रियान्वित 6
  • कार्रवाई A1 मान के साथ क्रियान्वित 7
  • कार्रवाई A1 मान के साथ क्रियान्वित 8
  • कार्रवाई A1 मान के साथ क्रियान्वित 9
  • कार्रवाई A1 मान के साथ क्रियान्वित 10

इससे पता चलता है कि केवल एक ही लक्ष्य वास्तव में सभी डेटा को निष्पादित कर रहा है, भले ही यह व्यस्त हो (थ्रेड स्लीप (100) उद्देश्य से जोड़ा गया)। क्यों?

इसका कारण यह है सभी लक्ष्य ब्लॉक प्रकृति में लालची डिफ़ॉल्ट रूप से कर रहे हैं और इनपुट भी बफ़र्स जब वे हम जबकि आरंभ DataFlowBlockOptions में गलत पर लालची संपत्ति की स्थापना की है data.To इस व्यवहार को बदलने की प्रक्रिया में सक्षम नहीं हैं जैसा कि नीचे दिखाया गया है एक्शनब्लॉक।

static void Main(string[] args) 
    { 
     BufferBlock<int> bb = new BufferBlock<int>(); 
     ActionBlock<int> a1 = new ActionBlock<int>((a) => 
                { 
                 Thread.Sleep(100); 
                 Console.WriteLine("Action A1 executing with value {0}", a); 
                } 
                , new DataflowBlockOptions(taskScheduler: TaskScheduler.Default, 
                      maxDegreeOfParallelism: 1, maxMessagesPerTask: 1, 
                      cancellationToken: CancellationToken.None, 
                      //Not Greedy 
                      greedy: false) 
               ); 

     ActionBlock<int> a2 = new ActionBlock<int>((a) => 
                { 
                 Thread.Sleep(50); 
                 Console.WriteLine("Action A2 executing with value {0}", a); 
                } 
                , new DataflowBlockOptions(taskScheduler: TaskScheduler.Default, 
                      maxDegreeOfParallelism: 1, maxMessagesPerTask: -1, 
                      cancellationToken: CancellationToken.None, 
                      greedy: false) 
               ); 
     ActionBlock<int> a3 = new ActionBlock<int>((a) => 
                { 
                 Thread.Sleep(50); 
                 Console.WriteLine("Action A3 executing with value {0}", a); 
                } 
                , new DataflowBlockOptions(taskScheduler: TaskScheduler.Default, 
                      maxDegreeOfParallelism: 1, maxMessagesPerTask: -1, 
                      cancellationToken: CancellationToken.None, 
                      greedy: false) 
               ); 
     bb.LinkTo(a1); 
     bb.LinkTo(a2); 
     bb.LinkTo(a3); 
     Task t = new Task(() => 
          { 
           int i = 0; 
           while (i < 10) 
           { 
            Thread.Sleep(50); 
            i++; 
            bb.Post(i); 
           } 
          } 
         ); 
     t.Start(); 
     Console.Read(); 
    } 

इस कार्यक्रम का उत्पादन होता है:

  • कार्रवाई A1 मान के साथ क्रियान्वित 1
  • कार्रवाई A2 मूल्य के साथ क्रियान्वित 3
  • कार्रवाई A1 2
  • कार्रवाई ए 3 क्रियान्वित मूल्य के साथ क्रियान्वित मूल्य 6
  • एक्शन ए 3 निष्पादन मूल्य 7
  • के साथकार्रवाई A3 मूल्य के साथ क्रियान्वित 8
  • कार्रवाई A2 मूल्य 5
  • कार्रवाई A3 मूल्य के साथ क्रियान्वित 9
  • कार्रवाई A1 4
  • कार्रवाई A2 मूल्य के साथ क्रियान्वित मूल्य के साथ क्रियान्वित 10

इस के साथ क्रियान्वित उम्मीद के अनुसार तीन एक्शनब्लॉक (एस) में डेटा का स्पष्ट रूप से वितरण।

+0

संकलन के लिए दूसरा उदाहरण नहीं मिला। – Nathan

4

नहीं, दूसरा उदाहरण कई कारणों से संकलित नहीं होगा: केवल "समूह" डेटाफ्लो ब्लॉक के लिए लालची = झूठी सेट करना संभव है - निष्पादन ब्लॉक के लिए नहीं; और उसके बाद इसे GroupingDataflowBlockOptions के माध्यम से सेट किया जाना है - डेटाफ्लोब्लॉकऑप्शन नहीं; और फिर इसे एक गुण मूल्य "{लालची = झूठा}" के रूप में सेट किया गया है जो कि कन्स्ट्रक्टर पैरामीटर नहीं है।

आप एक कार्रवाई ब्लॉक की क्षमता थ्रोटल चाहते हैं, यह (हालांकि ओपी कहा गया है, वे पहले से ही इस विकल्प के बारे में पता कर रहे हैं) DataflowBlockOptions की BoundedCapacity संपत्ति का मूल्य निर्धारित करके करते हैं।इस तरह:

var a1 = new ActionBlock<int>(
      i => doSomeWork(i), 
      new ExecutionDataflowBlockOptions {BoundedCapacity = 1} 
     );