共用方式為


HOW TO:使用訊息區篩選條件

本文件示範如何使用篩選函式,讓非同步訊息區塊根據訊息裝載來接受或拒絕訊息。

當您建立訊息區塊物件,例如 Concurrency::unbounded_bufferConcurrency::callConcurrency::transformer 時,可以提供「篩選函式」(Filter Function),決定訊息區塊會接受或拒絕訊息。 篩選函式是確保訊息區塊只接收特定值的實用方法。

篩選函式很重要,因為它們可讓您連接訊息區塊以形成「資料流程網路」(Dataflow Network)。 在資料流程網路中,訊息區塊只會處理符合特定準則的訊息,藉以控制資料流程。 相較之下,在控制流程模型中,資料流程是透過條件陳述式、迴圈等控制結構來規範。

本文件提供如何使用訊息篩選條件的基本範例。 如需使用訊息篩選條件和資料流程模型以連接訊息區塊的其他範例,請參閱逐步解說:建立資料流程代理程式逐步解說:建立影像處理網路

範例

請考慮下列函式 count_primes,這說明不篩選傳入訊息的訊息區塊基本用法。 此訊息區塊會將質數附加至 std::vector 物件。 count_primes 函式會傳送數個數字至訊息區塊,從訊息區塊接收輸出值,然後將質數列印至主控台。

// Illustrates usage of a message buffer that does not use filtering.
void count_primes(unsigned long random_seed)
{
   // Holds prime numbers.
   vector<unsigned long> primes;

   // Adds numbers that are prime to the vector object.
   transformer<unsigned long, unsigned long> t(
      [&primes](unsigned long n) -> unsigned long {
         if (is_prime(n))
            primes.push_back(n);
         return n;
      }
   );

   // Send random values to the message buffer.
   mt19937 generator(random_seed);
   for (int i = 0; i < 20; ++i)
      send(t, generator()%10000);

   // Receive from the message buffer the same number of times
   // to ensure that the message buffer has processed each message.
   for (int i = 0; i < 20; ++i)
      receive(t);

   // Print the prime numbers to the console.
   wcout << L"The following numbers are prime: " << endl;
   for_each(primes.begin(), primes.end(), [](unsigned long prime) {
      wcout << prime << endl;
   });
}

transformer 物件會處理所有輸入值,不過,它只需要質數值。 雖然應用程式撰寫方式可讓訊息傳送者只傳送質數,但訊息接收者的需求不一定是已知。

下列函式 count_primes_filter 會執行與 count_primes 函式相同的工作。 不過,這個版本中 transformer 物件使用篩選函式,只接受質數值。 執行動作的函式只接收質數,因此,它不必呼叫 is_prime 函式。

因為 transformer 物件只接收質數,所以 transformer 物件本身可以保存質數。 換言之,這個範例中的 transformer 物件不需要將質數加入至 vector 物件。

// Illustrates usage of a message buffer that uses filtering.
void count_primes_filter(unsigned long random_seed)
{
   // Accepts numbers that are prime.
   transformer<unsigned long, unsigned long> t(
      [](unsigned long n) -> unsigned long {
         // The filter function guarantees that the input value is prime.
         // Return the input value.
         return n;
      },
      NULL,      
      [](unsigned long n) -> bool {
         // Filter only values that are prime.
         return is_prime(n);
      }
   );

   // Send random values to the message buffer.
   mt19937 generator(random_seed);
   size_t prime_count = 0;
   for (int i = 0; i < 20; ++i)
      if (send(t, generator()%10000))
         ++prime_count;

   // Print the prime numbers to the console. 
   wcout << L"The following numbers are prime: " << endl;
   while (prime_count-- > 0)
      wcout << receive(t) << endl;
}

transformer 物件現在只會處理質數值。 在前述範例中,transformer 物件會處理所有訊息。 因此,前述範例必須接收與所傳送相同數目的訊息。 這個範例會使用 Concurrency::send 函式的結果,判斷要從 transformer 物件接收多少訊息。 如果訊息緩衝區接受訊息,send 函式會傳回 true,如果訊息緩衝區拒絕訊息則傳回 false。 因此,訊息緩衝區接受訊息的次數會符合質數計數。

下列程式碼顯示完整範例。 範例會呼叫 count_primes 函式和 count_primes_filter 函式。

// primes-filter.cpp
// compile with: /EHsc
#include <agents.h>
#include <algorithm>
#include <iostream>
#include <random>

using namespace Concurrency;
using namespace std;

// Determines whether the input value is prime.
bool is_prime(unsigned long n)
{
   if (n < 2)
      return false;
   for (unsigned long i = 2; i < n; ++i)
   {
      if ((n % i) == 0)
         return false;
   }
   return true;
}

// Illustrates usage of a message buffer that does not use filtering.
void count_primes(unsigned long random_seed)
{
   // Holds prime numbers.
   vector<unsigned long> primes;

   // Adds numbers that are prime to the vector object.
   transformer<unsigned long, unsigned long> t(
      [&primes](unsigned long n) -> unsigned long {
         if (is_prime(n))
            primes.push_back(n);
         return n;
      }
   );

   // Send random values to the message buffer.
   mt19937 generator(random_seed);
   for (int i = 0; i < 20; ++i)
      send(t, generator()%10000);

   // Receive from the message buffer the same number of times
   // to ensure that the message buffer has processed each message.
   for (int i = 0; i < 20; ++i)
      receive(t);

   // Print the prime numbers to the console.
   wcout << L"The following numbers are prime: " << endl;
   for_each(primes.begin(), primes.end(), [](unsigned long prime) {
      wcout << prime << endl;
   });
}

// Illustrates usage of a message buffer that uses filtering.
void count_primes_filter(unsigned long random_seed)
{
   // Accepts numbers that are prime.
   transformer<unsigned long, unsigned long> t(
      [](unsigned long n) -> unsigned long {
         // The filter function guarantees that the input value is prime.
         // Return the input value.
         return n;
      },
      NULL,      
      [](unsigned long n) -> bool {
         // Filter only values that are prime.
         return is_prime(n);
      }
   );

   // Send random values to the message buffer.
   mt19937 generator(random_seed);
   size_t prime_count = 0;
   for (int i = 0; i < 20; ++i)
      if (send(t, generator()%10000))
         ++prime_count;

   // Print the prime numbers to the console. 
   wcout << L"The following numbers are prime: " << endl;
   while (prime_count-- > 0)
      wcout << receive(t) << endl;
}

int wmain()
{
   const unsigned long random_seed = 99714;

   wcout << L"Without filtering:" << endl;
   count_primes(random_seed);

   wcout << L"With filtering:" << endl;
   count_primes_filter(random_seed);
}

這個範例會產生下列輸出:

Without filtering:
The following numbers are prime:
9973
9349
9241
8893
1297
7127
8647
3229
With filtering:
The following numbers are prime:
9973
9349
9241
8893
1297
7127
8647
3229

編譯程式碼

請複製範例程式碼,並將它貼在 Visual Studio 專案中,或貼在名為 primes-filter.cpp 的檔案中,然後在 Visual Studio 2010 的 [命令提示字元] 視窗中執行下列命令。

cl.exe /EHsc primes-filter.cpp

穩固程式設計

篩選函式可以是 Lambda 函式、函式指標或函式物件。 每個篩選函式都採用下列其中一個形式:

bool (_Type)
bool (_Type const &)

若要排除不必要的資料複製,當您的彙總型別是以傳值方式傳輸時,請使用第二個形式。

請參閱

參考

transformer 類別

概念

非同步代理程式程式庫

其他資源

逐步解說:建立資料流程代理程式

逐步解說:建立影像處理網路