비동기 메시지 블록Asynchronous Message Blocks

에이전트 라이브러리는 여러 메시지 블록 형식을 제공 하 여 스레드로부터 안전한 방식으로 응용 프로그램 구성 요소 간에 메시지를 전파할 수 있습니다.The Agents Library provides several message-block types that enable you to propagate messages among application components in a thread-safe manner. 이러한 메시지 블록 형식은 동시성:: send, concurrency:: asend, concurrency:: receiveconcurrency:: try_receive와 같은 다양 한 메시지 전달 루틴에서 주로 사용 됩니다.These message-block types are often used with the various message-passing routines, such as concurrency::send, concurrency::asend, concurrency::receive, and concurrency::try_receive. 에이전트 라이브러리에 의해 정의 되는 메시지 전달 루틴에 대 한 자세한 내용은 메시지 전달 함수를 참조 하세요.For more information about the message passing routines that are defined by the Agents Library, see Message Passing Functions.

섹션이Sections

이 항목에는 다음과 같은 섹션이 포함되어 있습니다.This topic contains the following sections:

원본 및 대상Sources and Targets

원본 및 대상은 메시지 전달 시 중요 한 두 참가자입니다.Sources and targets are two important participants in message passing. 소스 는 메시지를 보내는 통신의 끝점을 참조 합니다.A source refers to an endpoint of communication that sends messages. 대상은 메시지를 수신 하는 통신의 끝점을 참조 합니다.A target refers to an endpoint of communication that receives messages. 소스를에서 읽은 끝점으로 간주 하 고 대상을에 작성 하는 끝점으로 간주할 수 있습니다.You can think of a source as an endpoint that you read from and a target as an endpoint that you write to. 응용 프로그램은 원본 및 대상을 함께 연결 하 여 메시징 네트워크를 형성 합니다.Applications connect sources and targets together to form messaging networks.

에이전트 라이브러리는 두 개의 추상 클래스를 사용 하 여 소스 및 대상을 나타냅니다. concurrency:: ISourceConcurrency:: ITarget.The Agents Library uses two abstract classes to represent sources and targets: concurrency::ISource and concurrency::ITarget. 소스로 작동 하는 메시지 블록 형식은에서 파생 되며 ISource 대상으로 작동 하는 메시지 블록 형식은에서 파생 ITarget 됩니다.Message block types that act as sources derive from ISource; message block types that act as targets derive from ITarget. 소스 및 대상 역할을 하는 메시지 블록 형식은와 모두에서 파생 ISource ITarget 됩니다.Message block types that act as sources and targets derive from both ISource and ITarget.

[맨 위로이동][Top]

메시지 전파Message Propagation

메시지 전파 는 한 구성 요소에서 다른 구성 요소로 메시지를 전송 하는 동작입니다.Message propagation is the act of sending a message from one component to another. 메시지 블록에 메시지가 제공 되 면 해당 메시지를 수락, 거부 또는 연기할 수 있습니다.When a message block is offered a message, it can accept, decline, or postpone that message. 모든 메시지 블록 형식은 다양 한 방법으로 메시지를 저장 하 고 전송 합니다.Every message block type stores and transmits messages in different ways. 예를 들어, unbounded_buffer 클래스는 무제한의 메시지를 저장 하 고, 클래스는 한 overwrite_buffer 번에 하나의 메시지를 저장 하며, 변환기 클래스는 각 메시지의 변경 된 버전을 저장 합니다.For example, the unbounded_buffer class stores an unlimited number of messages, the overwrite_buffer class stores a single message at a time, and the transformer class stores an altered version of each message. 이러한 메시지 블록 형식은이 문서의 뒷부분에서 자세히 설명 합니다.These message block types are described in more detail later in this document.

메시지 블록이 메시지를 수락 하는 경우 선택적으로 작업을 수행 하 고, 메시지 블록이 원본인 경우 결과 메시지를 네트워크의 다른 구성원에 게 전달 합니다.When a message block accepts a message, it can optionally perform work and, if the message block is a source, pass the resulting message to another member of the network. 메시지 블록은 필터 함수를 사용 하 여 수신 하지 않으려는 메시지를 거부할 수 있습니다.A message block can use a filter function to decline messages that it does not want to receive. 필터는이 항목의 뒷부분에 있는 메시지 필터링섹션에서 자세히 설명 합니다.Filters are described in more detail later in this topic, in the section Message Filtering. 메시지를 연기 하는 메시지 블록은 메시지를 예약 하 고 나중에 사용할 수 있습니다.A message block that postpones a message can reserve that message and consume it later. 메시지 예약은이 항목의 뒷부분에 있는 메시지 예약섹션에서 자세히 설명 합니다.Message reservation is described in more detail later in this topic, in the section Message Reservation.

에이전트 라이브러리를 사용 하면 메시지 블록에서 메시지를 비동기적으로 또는 동기적으로 전달할 수 있습니다.The Agents Library enables message blocks to asynchronously or synchronously pass messages. 예를 들어 함수를 사용 하 여 메시지 블록에 메시지를 동기적으로 전달 하는 경우 send 런타임에서는 대상 블록이 메시지를 수락 하거나 거부할 때까지 현재 컨텍스트를 차단 합니다.When you pass a message to a message block synchronously, for example, by using the send function, the runtime blocks the current context until the target block either accepts or rejects the message. 예를 들어 함수를 사용 하 여 메시지 블록에 메시지를 비동기적으로 전달 하는 경우 asend 런타임에서는 대상에 메시지를 제공 하 고 대상이 메시지를 수락 하는 경우 런타임은 메시지를 받는 사람에 게 전파 하는 비동기 작업을 예약 합니다.When you pass a message to a message block asynchronously, for example, by using the asend function, the runtime offers the message to the target, and if the target accepts the message, the runtime schedules an asynchronous task that propagates the message to the receiver. 런타임은 간단한 작업을 사용 하 여 협조적 방식으로 메시지를 전파 합니다.The runtime uses lightweight tasks to propagate messages in a cooperative manner. 간단한 작업에 대 한 자세한 내용은 작업 스케줄러를 참조 하세요.For more information about lightweight tasks, see Task Scheduler.

응용 프로그램은 원본 및 대상을 함께 연결 하 여 메시징 네트워크를 형성 합니다.Applications connect sources and targets together to form messaging networks. 일반적으로 네트워크를 연결 하 고 send 또는 asend 를 호출 하 여 네트워크에 데이터를 전달 합니다.Typically, you link the network and call send or asend to pass data to the network. 소스 메시지 블록을 대상에 연결 하려면 concurrency:: ISource:: link_target 메서드를 호출 합니다.To connect a source message block to a target, call the concurrency::ISource::link_target method. 대상에서 소스 블록의 연결을 끊으려면 concurrency:: ISource:: unlink_target 메서드를 호출 합니다.To disconnect a source block from a target, call the concurrency::ISource::unlink_target method. 모든 대상에서 소스 블록의 연결을 끊으려면 concurrency:: ISource:: unlink_targets 메서드를 호출 합니다.To disconnect a source block from all of its targets, call the concurrency::ISource::unlink_targets method. 미리 정의 된 메시지 블록 형식 중 하나가 범위를 벗어나거나 소멸 되 면 모든 대상 블록에서 자동으로 연결을 끊습니다.When one of the predefined message block types leaves scope or is destroyed, it automatically disconnects itself from any target blocks. 일부 메시지 블록 형식은 쓸 수 있는 대상의 최대 수를 제한 합니다.Some message block types restrict the maximum number of targets that they can write to. 다음 섹션에서는 미리 정의 된 메시지 블록 형식에 적용 되는 제한 사항에 대해 설명 합니다.The following section describes the restrictions that apply to the predefined message block types.

[맨 위로이동][Top]

메시지 블록 형식 개요Overview of Message Block Types

다음 표에서는 중요 한 메시지 블록 형식의 역할에 대해 간략하게 설명 합니다.The following table briefly describes the role of the important message-block types.

unbounded_bufferunbounded_buffer
메시지 큐를 저장 합니다.Stores a queue of messages.

overwrite_bufferoverwrite_buffer
여러 번 읽고 쓸 수 있는 메시지 하나를 저장 합니다.Stores one message that can be written to and read from multiple times.

single_assignmentsingle_assignment
한 번에 쓸 수 있고 여러 번 읽을 수 있는 메시지 하나를 저장 합니다.Stores one message that can be written to one time and read from multiple times.

callcall
메시지를 받을 때 작업을 수행 합니다.Performs work when it receives a message.

transformer
는 데이터를 받을 때 작업을 수행 하 고 해당 작업의 결과를 다른 대상 블록으로 보냅니다.Performs work when it receives data and sends the result of that work to another target block. transformer클래스는 다양 한 입력 및 출력 형식에 대해 작동할 수 있습니다.The transformer class can act on different input and output types.

choicechoice
원본 집합에서 사용 가능한 첫 번째 메시지를 선택 합니다.Selects the first available message from a set of sources.

join 및 다중 형식 joinjoin and multitype join
원본 집합에서 모든 메시지가 수신 될 때까지 기다린 다음 메시지를 다른 메시지 블록에 대 한 하나의 메시지로 결합 합니다.Wait for all messages to be received from a set of sources and then combine the messages into one message for another message block.

시간이timer
는 일정 한 간격으로 대상 블록에 메시지를 보냅니다.Sends a message to a target block on a regular interval.

이러한 메시지 블록 형식은 다양 한 상황에서 유용 하 게 사용할 수 있는 다양 한 특성을 가집니다.These message-block types have different characteristics that make them useful for different situations. 이러한 특성은 다음과 같습니다.These are some of the characteristics:

  • 전파 유형: 메시지 블록이 데이터 원본, 데이터의 수신자 또는 둘 다의 역할을 하는지 여부입니다.Propagation type: Whether the message block acts as a source of data, a receiver of data, or both.

  • 메시지 순서: 메시지 블록에서 메시지를 보내거나 받는 원래 순서를 유지할지 여부를 지정 합니다.Message ordering: Whether the message block maintains the original order in which messages are sent or received. 미리 정의 된 각 메시지 블록 형식은 메시지를 보내거나 받는 원래 순서를 유지 합니다.Each predefined message block type maintains the original order in which it sends or receives messages.

  • 소스 수: 메시지 블록에서 읽을 수 있는 최대 소스 수입니다.Source count: The maximum number of sources that the message block can read from.

  • 대상 개수: 메시지 블록이 쓸 수 있는 최대 대상 수입니다.Target count: The maximum number of targets that the message block can write to.

다음 표에서는 이러한 특성이 다양 한 메시지 블록 형식과 어떻게 관련 되는지를 보여 줍니다.The following table shows how these characteristics relate to the various message-block types.

메시지 블록 형식Message block type 전파 유형 (원본, 대상 또는 둘 다)Propagation type (Source, Target, or Both) 메시지 순서 지정 (정렬 또는 정렬 되지 않음)Message ordering (Ordered or Unordered) 원본 수Source count 대상 개수Target count
unbounded_buffer 둘 다Both 주문됨Ordered UnboundedUnbounded UnboundedUnbounded
overwrite_buffer 둘 다Both 주문됨Ordered UnboundedUnbounded UnboundedUnbounded
single_assignment 둘 다Both 주문됨Ordered UnboundedUnbounded UnboundedUnbounded
call 대상Target 주문됨Ordered UnboundedUnbounded 해당 사항 없음Not Applicable
transformer 둘 다Both 주문됨Ordered UnboundedUnbounded 11
choice 둘 다Both 주문됨Ordered 1010 11
join 둘 다Both 주문됨Ordered UnboundedUnbounded 11
multitype_join 둘 다Both 주문됨Ordered 1010 11
timer 원본Source 해당 사항 없음Not Applicable 해당 사항 없음Not Applicable 11

다음 섹션에서는 메시지 블록 형식에 대해 자세히 설명 합니다.The following sections describe the message-block types in more detail.

[맨 위로이동][Top]

unbounded_buffer 클래스unbounded_buffer Class

Concurrency:: unbounded_buffer 클래스는 범용 비동기 메시징 구조를 나타냅니다.The concurrency::unbounded_buffer class represents a general-purpose asynchronous messaging structure. 이 클래스는 여러 소스가 기록하거나 여러 대상이 읽을 수 있는 메시지의 FIFO(선입 선출) 큐를 저장합니다.This class stores a first in, first out (FIFO) queue of messages that can be written to by multiple sources or read from by multiple targets. 대상이 개체에서 메시지를 받으면 unbounded_buffer 해당 메시지는 메시지 큐에서 제거 됩니다.When a target receives a message from an unbounded_buffer object, that message is removed from the message queue. 따라서 unbounded_buffer 개체에 대상이 여러 개 있을 수 있지만 하나의 대상만 각 메시지를 받습니다.Therefore, although an unbounded_buffer object can have multiple targets, only one target will receive each message. unbounded_buffer 클래스는 여러 메시지를 다른 구성 요소에 전달하려고 할 때 유용하고 해당 구성 요소는 각 메시지를 수신해야 합니다.The unbounded_buffer class is useful when you want to pass multiple messages to another component, and that component must receive each message.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 unbounded_buffer .The following example shows the basic structure of how to work with the unbounded_buffer class. 이 예제에서는 세 개의 값을 unbounded_buffer 개체에 보낸 다음 동일한 개체에서 해당 값을 다시 읽습니다.This example sends three values to an unbounded_buffer object and then reads those values back from the same object.

// unbounded_buffer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an unbounded_buffer object that works with
   // int data.
   unbounded_buffer<int> items;

   // Send a few items to the unbounded_buffer object.
   send(items, 33);
   send(items, 44);
   send(items, 55);

   // Read the items from the unbounded_buffer object and print
   // them to the console.
   wcout << receive(items) << endl;
   wcout << receive(items) << endl;
   wcout << receive(items) << endl;
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

334455

클래스를 사용 하는 방법을 보여 주는 전체 예제는 unbounded_buffer 방법: 다양 한 생산자-소비자 패턴 구현을 참조 하세요.For a complete example that shows how to use the unbounded_buffer class, see How to: Implement Various Producer-Consumer Patterns.

[맨 위로이동][Top]

overwrite_buffer 클래스overwrite_buffer Class

Concurrency:: overwrite_buffer 클래스는 클래스와 유사 unbounded_buffer 합니다. 단, overwrite_buffer 개체는 하나의 메시지만 저장 합니다.The concurrency::overwrite_buffer class resembles the unbounded_buffer class, except that an overwrite_buffer object stores just one message. 또한 대상이 개체에서 메시지를 받으면 overwrite_buffer 해당 메시지는 버퍼에서 제거 되지 않습니다.In addition, when a target receives a message from an overwrite_buffer object, that message is not removed from the buffer. 따라서 여러 대상이 하나의 메시지 복사본을 수신합니다.Therefore, multiple targets receive a copy of the message.

overwrite_buffer클래스는 여러 메시지를 다른 구성 요소에 전달 하려는 경우에 유용 하지만 해당 구성 요소에는 최신 값만 필요 합니다.The overwrite_buffer class is useful when you want to pass multiple messages to another component, but that component needs only the most recent value. 이 클래스는 여러 구성 요소에 메시지를 브로드캐스트하려고 할 때도 유용합니다.This class is also useful when you want to broadcast a message to multiple components.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 overwrite_buffer .The following example shows the basic structure of how to work with the overwrite_buffer class. 이 예제에서는 세 개의 값을 overwrite _buffer 개체에 보낸 다음 동일한 개체에서 현재 값을 세 번 읽습니다.This example sends three values to an overwrite _buffer object and then reads the current value from the same object three times. 이 예제는 클래스에 대 한 예제와 비슷합니다 unbounded_buffer .This example is similar to the example for the unbounded_buffer class. 그러나 클래스는 overwrite_buffer 하나의 메시지만 저장 합니다.However, the overwrite_buffer class stores just one message. 또한 개체를 읽은 후에는 개체에서 메시지를 제거 하지 않습니다 overwrite_buffer .In addition, the runtime does not remove the message from an overwrite_buffer object after it is read.

// overwrite_buffer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an overwrite_buffer object that works with
   // int data.
   overwrite_buffer<int> item;

   // Send a few items to the overwrite_buffer object.
   send(item, 33);
   send(item, 44);
   send(item, 55);

   // Read the current item from the overwrite_buffer object and print
   // it to the console three times.
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

555555

클래스를 사용 하는 방법을 보여 주는 전체 예제는 overwrite_buffer 방법: 다양 한 생산자-소비자 패턴 구현을 참조 하세요.For a complete example that shows how to use the overwrite_buffer class, see How to: Implement Various Producer-Consumer Patterns.

[맨 위로이동][Top]

single_assignment 클래스single_assignment Class

Concurrency:: single_assignment 클래스는 클래스와 유사 overwrite_buffer 합니다. 단, single_assignment 개체는 한 번만 쓸 수 있습니다.The concurrency::single_assignment class resembles the overwrite_buffer class, except that a single_assignment object can be written to one time only. overwrite_buffer 클래스처럼 대상이 single_assignment 개체에서 메시지를 수신할 때 해당 메시지는 해당 개체에서 제거되지 않습니다.Like the overwrite_buffer class, when a target receives a message from a single_assignment object, that message is not removed from that object. 따라서 여러 대상이 하나의 메시지 복사본을 수신합니다.Therefore, multiple targets receive a copy of the message. single_assignment클래스는 여러 구성 요소에 메시지 하나를 브로드캐스팅하 려는 경우에 유용 합니다.The single_assignment class is useful when you want to broadcast one message to multiple components.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 single_assignment .The following example shows the basic structure of how to work with the single_assignment class. 이 예제에서는 세 개의 값을 single_assignment 개체에 보낸 다음 동일한 개체에서 현재 값을 세 번 읽습니다.This example sends three values to a single_assignment object and then reads the current value from the same object three times. 이 예제는 클래스에 대 한 예제와 비슷합니다 overwrite_buffer .This example is similar to the example for the overwrite_buffer class. overwrite_buffer및 클래스는 모두 single_assignment 단일 메시지를 저장 하지만 클래스는 single_assignment 한 번만 쓸 수 있습니다.Although both the overwrite_buffer and single_assignment classes store a single message, the single_assignment class can be written to one time only.

// single_assignment-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an single_assignment object that works with
   // int data.
   single_assignment<int> item;

   // Send a few items to the single_assignment object.
   send(item, 33);
   send(item, 44);
   send(item, 55);

   // Read the current item from the single_assignment object and print
   // it to the console three times.
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

333333

클래스를 사용 하는 방법을 보여 주는 전체 예제는 single_assignment 연습: 미래 구현을 참조 하세요.For a complete example that shows how to use the single_assignment class, see Walkthrough: Implementing Futures.

[맨 위로이동][Top]

call 클래스call Class

Concurrency:: call 클래스는 데이터를 받을 때 작업 함수를 수행 하는 메시지 수신자 역할을 합니다.The concurrency::call class acts as a message receiver that performs a work function when it receives data. 이 작업 함수는 람다 식, 함수 개체 또는 함수 포인터 일 수 있습니다.This work function can be a lambda expression, a function object, or a function pointer. call개체는 메시지를 보내는 다른 구성 요소와 병렬로 동작 하기 때문에 일반 함수 호출과 다르게 동작 합니다.A call object behaves differently than an ordinary function call because it acts in parallel to other components that send messages to it. call개체가 메시지를 받을 때 작업을 수행 하는 경우 해당 메시지를 큐에 추가 합니다.If a call object is performing work when it receives a message, it adds that message to a queue. 모든 call 개체는 대기열에 있는 메시지를 받은 순서 대로 처리 합니다.Every call object processes queued messages in the order in which they are received.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 call .The following example shows the basic structure of how to work with the call class. 이 예제에서는 call 콘솔에 수신 하는 각 값을 출력 하는 개체를 만듭니다.This example creates a call object that prints each value that it receives to the console. 그런 다음이 예제에서는 세 개의 값을 개체에 보냅니다 call .The example then sends three values to the call object. 개체는 call 별도의 스레드에서 메시지를 처리 하기 때문에이 예제에서는 카운터 변수와 이벤트 개체를 사용 하 여 call 함수가 반환 되기 전에 개체가 모든 메시지를 처리 하도록 합니다 wmain .Because the call object processes messages on a separate thread, this example also uses a counter variable and an event object to ensure that the call object processes all messages before the wmain function returns.

// call-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // An event that is set when the call object receives all values.
   event received_all;

   // Counts the 
   long receive_count = 0L;
   long max_receive_count = 3L;

   // Create an call object that works with int data.
   call<int> target([&received_all,&receive_count,max_receive_count](int n) {
      // Print the value that the call object receives to the console.
      wcout << n << endl;
      
      // Set the event when all messages have been processed.
      if (++receive_count == max_receive_count)
         received_all.set();
   });

   // Send a few items to the call object.
   send(target, 33);
   send(target, 44);
   send(target, 55);

   // Wait for the call object to process all items.
   received_all.wait();
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

334455

클래스를 사용 하는 방법을 보여 주는 전체 예제는 call 방법: 호출 및 변환기 클래스에 작업 함수 제공을 참조 하세요.For a complete example that shows how to use the call class, see How to: Provide Work Functions to the call and transformer Classes.

[맨 위로이동][Top]

변환기 클래스transformer Class

Concurrency:: 변환기 클래스는 메시지 수신자와 메시지 전송자 역할을 합니다.The concurrency::transformer class acts as both a message receiver and as a message sender. transformer클래스는 call 데이터를 받을 때 사용자 정의 작업 함수를 수행 하기 때문에 클래스와 유사 합니다.The transformer class resembles the call class because it performs a user-defined work function when it receives data. 그러나 클래스는 transformer 작업 함수의 결과를 수신자 개체에도 보냅니다.However, the transformer class also sends the result of the work function to receiver objects. 개체와 마찬가지로 call 개체는 transformer 메시지를 보내는 다른 구성 요소와 병렬로 작동 합니다.Like a call object, a transformer object acts in parallel to other components that send messages to it. transformer개체가 메시지를 받을 때 작업을 수행 하는 경우 해당 메시지를 큐에 추가 합니다.If a transformer object is performing work when it receives a message, it adds that message to a queue. 모든 transformer 개체는 대기열에 있는 메시지를 받은 순서 대로 처리 합니다.Every transformer object processes its queued messages in the order in which they are received.

transformer클래스는 메시지를 하나의 대상으로 보냅니다.The transformer class sends its message to one target. _PTarget생성자의 매개 변수를로 설정 하는 경우 NULL 나중에 concurrency:: link_target 메서드를 호출 하 여 대상을 지정할 수 있습니다.If you set the _PTarget parameter in the constructor to NULL, you can later specify the target by calling the concurrency::link_target method.

에이전트 라이브러리에서 제공 하는 다른 모든 비동기 메시지 블록 형식과 달리 transformer 클래스는 다른 입력 및 출력 형식에 대해 작동할 수 있습니다.Unlike all other asynchronous message block types that are provided by the Agents Library, the transformer class can act on different input and output types. 데이터를 한 형식에서 다른 형식으로 변환 하는이 기능을 통해 transformer 클래스는 많은 동시 네트워크에서 키 구성 요소가 됩니다.This ability to transform data from one type to another makes the transformer class a key component in many concurrent networks. 또한 개체의 작업 함수에서 보다 세분화 된 병렬 기능을 추가할 수 있습니다 transformer .In addition, you can add more fine-grained parallel functionality in the work function of a transformer object.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 transformer .The following example shows the basic structure of how to work with the transformer class. 이 예제에서는 transformer int 값을 출력으로 생성 하기 위해 0.33에 따라 각 입력 값을 여러 개의 개체를 만듭니다 double .This example creates a transformer object that multiples each input int value by 0.33 in order to produce a double value as output. 그런 다음이 예제에서는 동일한 개체에서 변환 된 값을 받아 transformer 콘솔에 출력 합니다.The example then receives the transformed values from the same transformer object and prints them to the console.

// transformer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an transformer object that receives int data and 
   // sends double data.
   transformer<int, double> third([](int n) {
      // Return one-third of the input value.
      return n * 0.33;
   });

   // Send a few items to the transformer object.
   send(third, 33);
   send(third, 44);
   send(third, 55);

   // Read the processed items from the transformer object and print
   // them to the console.
   wcout << receive(third) << endl;
   wcout << receive(third) << endl;
   wcout << receive(third) << endl;
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

10.8914.5218.15

클래스를 사용 하는 방법을 보여 주는 전체 예제는 transformer 방법: 데이터 파이프라인에서 변환기 사용을 참조 하세요.For a complete example that shows how to use the transformer class, see How to: Use transformer in a Data Pipeline.

[맨 위로이동][Top]

choice 클래스choice Class

Concurrency:: choice 클래스는 소스 집합에서 사용 가능한 첫 번째 메시지를 선택 합니다.The concurrency::choice class selects the first available message from a set of sources. choice클래스는 데이터 흐름 메커니즘 대신 제어 흐름 메커니즘을 나타냅니다. 비동기 에이전트 라이브러리 항목에서는 데이터 흐름 및 제어 흐름 간의 차이점을 설명 합니다.The choice class represents a control-flow mechanism instead of a dataflow mechanism (the topic Asynchronous Agents Library describes the differences between dataflow and control-flow).

Choice 개체에서 읽기 WaitForMultipleObjectsbWaitAll 매개 변수가로 설정 된 경우 Windows API 함수를 호출 하는 것과 비슷합니다 FALSE .Reading from a choice object resembles calling the Windows API function WaitForMultipleObjects when it has the bWaitAll parameter set to FALSE. 그러나 클래스는 choice 외부 동기화 개체가 아닌 이벤트 자체에 데이터를 바인딩합니다.However, the choice class binds data to the event itself instead of to an external synchronization object.

일반적으로 choice 클래스를 concurrency:: receive 함수와 함께 사용 하 여 응용 프로그램에서 제어 흐름을 구동 합니다.Typically, you use the choice class together with the concurrency::receive function to drive control-flow in your application. choice형식이 다른 메시지 버퍼를 선택 해야 하는 경우 클래스를 사용 합니다.Use the choice class when you have to select among message buffers that have different types. single_assignment형식이 같은 메시지 버퍼를 선택 해야 하는 경우 클래스를 사용 합니다.Use the single_assignment class when you have to select among message buffers that have the same type.

소스를 개체에 연결 하는 순서는 choice 선택한 메시지를 결정할 수 있기 때문에 중요 합니다.The order in which you link sources to a choice object is important because it can determine which message is selected. 예를 들어 이미 메시지를 포함 하는 여러 메시지 버퍼를 개체에 연결 하는 경우를 고려해 보세요 choice .For example, consider the case where you link multiple message buffers that already contain a message to a choice object. choice개체는 연결 된 첫 번째 소스에서 메시지를 선택 합니다.The choice object selects the message from the first source that it is linked to. 모든 원본을 연결한 후 choice 개체는 각 원본에서 메시지를 수신 하는 순서를 유지 합니다.After you link all sources, the choice object preserves the order in which each source receives a message.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 choice .The following example shows the basic structure of how to work with the choice class. 이 예제에서는 concurrency:: make_choice 함수를 사용 하 여 choice 세 가지 메시지 블록 중에서 선택 하는 개체를 만듭니다.This example uses the concurrency::make_choice function to create a choice object that selects among three message blocks. 그런 다음이 예제에서는 다양 한 피보나치 수를 계산 하 고 각 결과를 다른 메시지 블록에 저장 합니다.The example then computes various Fibonacci numbers and stores each result in a different message block. 그런 다음이 예제에서는 먼저 완료 된 작업을 기반으로 하는 메시지를 콘솔에 출력 합니다.The example then prints to the console a message that is based on the operation that finished first.

// choice-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   // Although the following thee message blocks are written to one time only, 
   // this example illustrates the fact that the choice class works with 
   // different message block types.

   // Holds the 35th Fibonacci number.
   single_assignment<int> fib35;
   // Holds the 37th Fibonacci number.
   overwrite_buffer<int> fib37;
   // Holds half of the 42nd Fibonacci number.
   unbounded_buffer<double> half_of_fib42;   

   // Create a choice object that selects the first single_assignment 
   // object that receives a value.
   auto select_one = make_choice(&fib35, &fib37, &half_of_fib42);

   // Execute a few lengthy operations in parallel. Each operation sends its 
   // result to one of the single_assignment objects.
   parallel_invoke(
      [&fib35] { send(fib35, fibonacci(35)); },
      [&fib37] { send(fib37, fibonacci(37)); },
      [&half_of_fib42] { send(half_of_fib42, fibonacci(42) * 0.5); }
   );

   // Print a message that is based on the operation that finished first.
   switch (receive(select_one))
   {
   case 0:
      wcout << L"fib35 received its value first. Result = " 
            << receive(fib35) << endl;
      break;
   case 1:
      wcout << L"fib37 received its value first. Result = " 
            << receive(fib37) << endl;
      break;
   case 2:
      wcout << L"half_of_fib42 received its value first. Result = " 
            << receive(half_of_fib42) << endl;
      break;
   default:
      wcout << L"Unexpected." << endl;
      break;
   }
}

이 예제에서는 다음과 같은 샘플 출력을 생성 합니다.This example produces the following sample output:

fib35 received its value first. Result = 9227465

35 번째 피보나치 수를 계산 하는 작업은 먼저 완료 되도록 보장 되지 않으므로이 예제의 출력은 다를 수 있습니다.Because the task that computes the 35th Fibonacci number is not guaranteed to finish first, the output of this example can vary.

이 예제에서는 concurrency::p arallel_invoke 알고리즘을 사용 하 여 피보나치 수를 병렬로 계산 합니다.This example uses the concurrency::parallel_invoke algorithm to compute the Fibonacci numbers in parallel. 에 대 한 자세한 내용은 parallel_invoke 병렬 알고리즘을 참조 하세요.For more information about parallel_invoke, see Parallel Algorithms.

클래스를 사용 하는 방법을 보여 주는 전체 예제는 choice 방법: 완료 된 작업 중에서 선택을 참조 하세요.For a complete example that shows how to use the choice class, see How to: Select Among Completed Tasks.

[맨 위로이동][Top]

조인 및 multitype_join 클래스join and multitype_join Classes

Concurrency:: joinconcurrency:: multitype_join 클래스를 사용 하면 소스 집합의 각 멤버가 메시지를 받을 때까지 기다릴 수 있습니다.The concurrency::join and concurrency::multitype_join classes let you wait for each member of a set of sources to receive a message. join클래스는 일반적인 메시지 유형을 가진 소스 개체에 대해 작동 합니다.The join class acts on source objects that have a common message type. multitype_join클래스는 서로 다른 메시지 유형을 가질 수 있는 소스 개체에 대해 작동 합니다.The multitype_join class acts on source objects that can have different message types.

join또는 개체에서 읽기 multitype_join WaitForMultipleObjectsbWaitAll 매개 변수가로 설정 된 경우 Windows API 함수를 호출 하는 것과 비슷합니다 TRUE .Reading from a join or multitype_join object resembles calling the Windows API function WaitForMultipleObjects when it has the bWaitAll parameter set to TRUE. 그러나 개체와 마찬가지로 choice joinmultitype_join 개체는 외부 동기화 개체가 아닌 이벤트 자체에 데이터를 바인딩하는 이벤트 메커니즘을 사용 합니다.However, just like a choice object, join and multitype_join objects use an event mechanism that binds data to the event itself instead of to an external synchronization object.

개체를 읽으면 join std::vector 개체가 생성 됩니다.Reading from a join object produces a std::vector object. 개체를 읽으면 multitype_join std::tuple 개체가 생성 됩니다.Reading from a multitype_join object produces a std::tuple object. 요소는 이러한 개체에 해당 소스 버퍼가 나 개체에 연결 되는 것과 동일한 순서로 join 나타납니다 multitype_join .Elements appear in these objects in the same order as their corresponding source buffers are linked to the join or multitype_join object. 소스 버퍼를 또는 개체에 연결 하는 순서는 join multitype_join 결과 또는 개체의 요소 순서와 연결 되므로 vector tuple 조인에서 기존 소스 버퍼의 연결을 해제 하지 않는 것이 좋습니다.Because the order in which you link source buffers to a join or multitype_join object is associated with the order of elements in the resulting vector or tuple object, we recommend that you do not unlink an existing source buffer from a join. 이렇게 하면 지정 되지 않은 동작이 발생할 수 있습니다.Doing so can result in unspecified behavior.

Greedy 및 Non-greedy 조인Greedy Versus Non-Greedy Joins

joinmultitype_join 클래스는 greedy 조인과 non-greedy 조인의 개념을 지원 합니다.The join and multitype_join classes support the concept of greedy and non-greedy joins. Greedy 조인은 모든 메시지를 사용할 수 있을 때까지 메시지를 사용할 수 있게 되 면 각 소스의 메시지를 수락 합니다.A greedy join accepts a message from each of its sources as messages become available until all message are available. Non-greedy 조인은 두 단계로 메시지를 수신 합니다.A non-greedy join receives messages in two phases. 먼저 non-greedy 조인은 각 소스에서 메시지를 제공할 때까지 대기 합니다.First, a non-greedy join waits until it is offered a message from each of its sources. 둘째, 모든 원본 메시지를 사용할 수 있게 되 면 non-greedy 조인은 각 메시지를 예약 하려고 시도 합니다.Second, after all source messages are available, a non-greedy join attempts to reserve each of those messages. 각 메시지를 예약할 수 있는 경우 모든 메시지를 사용 하 여 대상에 전파 합니다.If it can reserve each message, it consumes all messages and propagates them to its target. 그렇지 않으면 메시지 예약을 해제 하거나 취소 하 고 각 소스가 메시지를 받을 때까지 기다립니다.Otherwise, it releases, or cancels, the message reservations and again waits for each source to receive a message.

Greedy 조인은 메시지를 즉시 허용 하므로 non-greedy 조인 보다 성능이 우수 합니다.Greedy joins perform better than non-greedy joins because they accept messages immediately. 그러나 드문 경우 이지만 non-greedy 조인은 교착 상태가 발생할 수 있습니다.However, in rare cases, greedy joins can lead to deadlocks. 하나 이상의 공유 원본 개체가 포함 된 조인이 여러 개 있는 경우 non-greedy 조인을 사용 합니다.Use a non-greedy join when you have multiple joins that contain one or more shared source objects.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 join .The following example shows the basic structure of how to work with the join class. 이 예제에서는 concurrency:: make_join 함수를 사용 하 여 join 세 개체에서 받는 개체를 만듭니다 single_assignment .This example uses the concurrency::make_join function to create a join object that receives from three single_assignment objects. 이 예제에서는 다양 한 피보나치 수를 계산 하 고, 각 결과를 다른 개체에 저장 한 single_assignment 다음 개체가 보유 하 고 있는 각 결과를 콘솔에 출력 join 합니다.This example computes various Fibonacci numbers, stores each result in a different single_assignment object, and then prints to the console each result that the join object holds. 이 예제는 클래스가 choice join 모든 소스 메시지 블록이 메시지를 받을 때까지 대기 한다는 점을 제외 하 고 클래스의 예제와 비슷합니다.This example is similar to the example for the choice class, except that the join class waits for all source message blocks to receive a message.

// join-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   // Holds the 35th Fibonacci number.
   single_assignment<int> fib35;
   // Holds the 37th Fibonacci number.
   single_assignment<int> fib37;
   // Holds half of the 42nd Fibonacci number.
   single_assignment<double> half_of_fib42;   

   // Create a join object that selects the values from each of the
   // single_assignment objects.
   auto join_all = make_join(&fib35, &fib37, &half_of_fib42);

   // Execute a few lengthy operations in parallel. Each operation sends its 
   // result to one of the single_assignment objects.
   parallel_invoke(
      [&fib35] { send(fib35, fibonacci(35)); },
      [&fib37] { send(fib37, fibonacci(37)); },
      [&half_of_fib42] { send(half_of_fib42, fibonacci(42) * 0.5); }
   );

   auto result = receive(join_all);
   wcout << L"fib35 = " << get<0>(result) << endl;
   wcout << L"fib37 = " << get<1>(result) << endl;
   wcout << L"half_of_fib42 = " << get<2>(result) << endl;
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

fib35 = 9227465fib37 = 24157817half_of_fib42 = 1.33957e+008

이 예제에서는 concurrency::p arallel_invoke 알고리즘을 사용 하 여 피보나치 수를 병렬로 계산 합니다.This example uses the concurrency::parallel_invoke algorithm to compute the Fibonacci numbers in parallel. 에 대 한 자세한 내용은 parallel_invoke 병렬 알고리즘을 참조 하세요.For more information about parallel_invoke, see Parallel Algorithms.

클래스 사용 방법을 보여 주는 전체 예제 join 는 방법: 완료 된 작업 중에서 선택연습: Join을 사용 하 여 교착 상태 방지를 참조 하세요.For complete examples that show how to use the join class, see How to: Select Among Completed Tasks and Walkthrough: Using join to Prevent Deadlock.

[맨 위로이동][Top]

timer 클래스timer Class

Concurrency::timer 클래스 는 메시지 원본 역할을 합니다.The concurrency::timer class acts as a message source. timer지정 된 시간이 경과 된 후 개체에서 대상으로 메시지를 보냅니다.A timer object sends a message to a target after a specified period of time has elapsed. timer클래스는 메시지 전송을 지연 하거나 메시지를 정기적으로 전송 하려는 경우에 유용 합니다.The timer class is useful when you must delay sending a message or you want to send a message at a regular interval.

timer클래스는 메시지를 하나의 대상에만 보냅니다.The timer class sends its message to just one target. _PTarget생성자의 매개 변수를로 설정 하는 경우 NULL 나중에 Concurrency:: ISource:: link_target 메서드를 호출 하 여 대상을 지정할 수 있습니다.If you set the _PTarget parameter in the constructor to NULL, you can later specify the target by calling the concurrency::ISource::link_target method.

timer개체는 반복 되거나 반복 되지 않을 수 있습니다.A timer object can be repeating or non-repeating. 반복 타이머를 만들려면 true _Repeating 생성자를 호출할 때 매개 변수에 대 한를 전달 합니다.To create a repeating timer, pass true for the _Repeating parameter when you call the constructor. 그렇지 않으면 false _Repeating 매개 변수를 전달 하 여 반복 되지 않는 타이머를 만듭니다.Otherwise, pass false for the _Repeating parameter to create a non-repeating timer. 타이머가 반복 되는 경우 각 간격 후에 동일한 메시지를 대상으로 보냅니다.If the timer is repeating, it sends the same message to its target after each interval.

에이전트 라이브러리는 timer 개체를 시작 되지 않은 상태로 만듭니다.The Agents Library creates timer objects in the non-started state. Timer 개체를 시작 하려면 concurrency:: timer:: start 메서드를 호출 합니다.To start a timer object, call the concurrency::timer::start method. 개체를 중지 하려면 timer 개체를 삭제 하거나 concurrency:: timer:: stop 메서드를 호출 합니다.To stop a timer object, destroy the object or call the concurrency::timer::stop method. 반복 되는 타이머를 일시 중지 하려면 concurrency:: timer::p ause 메서드를 호출 합니다.To pause a repeating timer, call the concurrency::timer::pause method.

예제Example

다음 예제에서는 클래스를 사용 하는 방법의 기본 구조를 보여 줍니다 timer .The following example shows the basic structure of how to work with the timer class. 이 예제에서는 timercall 개체를 사용 하 여 시간이 오래 걸리는 작업의 진행률을 보고 합니다.The example uses timer and call objects to report the progress of a lengthy operation.

// timer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   // Create a call object that prints characters that it receives 
   // to the console.
   call<wchar_t> print_character([](wchar_t c) {
      wcout << c;
   });

   // Create a timer object that sends the period (.) character to 
   // the call object every 100 milliseconds.
   timer<wchar_t> progress_timer(100u, L'.', &print_character, true);

   // Start the timer.
   wcout << L"Computing fib(42)";
   progress_timer.start();

   // Compute the 42nd Fibonacci number.
   int fib42 = fibonacci(42);

   // Stop the timer and print the result.
   progress_timer.stop();
   wcout << endl << L"result is " << fib42 << endl;
}

이 예제에서는 다음과 같은 샘플 출력을 생성 합니다.This example produces the following sample output:

Computing fib(42)..................................................result is 267914296

클래스를 사용 하는 방법을 보여 주는 전체 예제는 timer 방법: 정기적으로 메시지 보내기를 참조 하세요.For a complete example that shows how to use the timer class, see How to: Send a Message at a Regular Interval.

[맨 위로이동][Top]

메시지 필터링Message Filtering

메시지 블록 개체를 만들 때 메시지 블록이 메시지를 수락 하거나 거부 하는지 여부를 결정 하는 필터 함수 를 제공할 수 있습니다.When you create a message block object, you can supply a filter function that determines whether the message block accepts or rejects a message. 필터 함수는 메시지 블록이 특정 값만 받도록 보장 하는 유용한 방법입니다.A filter function is a useful way to guarantee that a message block receives only certain values.

다음 예제에서는 unbounded_buffer 필터 함수를 사용 하 여 짝수만 허용 하는 개체를 만드는 방법을 보여 줍니다.The following example shows how to create an unbounded_buffer object that uses a filter function to accept only even numbers. unbounded_buffer개체는 홀수를 거부 하므로 짝수의 숫자를 대상 블록에 전파 하지 않습니다.The unbounded_buffer object rejects odd numbers, and therefore does not propagate odd numbers to its target blocks.

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

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an unbounded_buffer object that uses a filter
   // function to accept only even numbers.
   unbounded_buffer<int> accept_evens(
      [](int n) {
         return (n%2) == 0;
      });

   // Send a few values to the unbounded_buffer object.
   unsigned int accept_count = 0;
   for (int i = 0; i < 10; ++i)
   {
      // The asend function returns true only if the target
      // accepts the message. This enables us to determine
      // how many elements are stored in the unbounded_buffer
      // object.
      if (asend(accept_evens, i))
      {
         ++accept_count;
      }
   }

   // Print to the console each value that is stored in the 
   // unbounded_buffer object. The unbounded_buffer object should
   // contain only even numbers.
   while (accept_count > 0)
   {
      wcout << receive(accept_evens) << L' ';
      --accept_count;
   }
}

이 예제는 다음과 같은 출력을 생성합니다.This example produces the following output:

0 2 4 6 8

필터 함수는 람다 함수, 함수 포인터 또는 함수 개체 일 수 있습니다.A filter function can be a lambda function, a function pointer, or a function object. 모든 필터 함수는 다음 형식 중 하나를 사용 합니다.Every filter function takes one of the following forms.

bool (T)
bool (T const &)

불필요 한 데이터 복사를 제거 하려면 값으로 전파 되는 집계 형식이 있는 경우 두 번째 형식을 사용 합니다.To eliminate the unnecessary copying of data, use the second form when you have an aggregate type that is propagated by value.

메시지 필터링은 구성 요소가 데이터를 받을 때 계산을 수행 하는 데이터 흐름 프로그래밍 모델을 지원 합니다.Message filtering supports the dataflow programming model, in which components perform computations when they receive data. 필터 함수를 사용 하 여 네트워크를 통과 하는 메시지의 데이터 흐름을 제어 하는 예제는 방법: 메시지 블록 필터 사용, 연습: 데이터 흐름 에이전트 만들기연습: 이미지 처리 네트워크 만들기를 참조 하세요.For examples that use filter functions to control the flow of data in a message passing network, see How to: Use a Message Block Filter, Walkthrough: Creating a Dataflow Agent, and Walkthrough: Creating an Image-Processing Network.

[맨 위로이동][Top]

메시지 예약Message Reservation

메시지 예약 을 사용 하면 메시지 블록에서 나중에 사용할 메시지를 예약할 수 있습니다.Message reservation enables a message block to reserve a message for later use. 일반적으로 메시지 예약은 직접 사용 되지 않습니다.Typically, message reservation is not used directly. 그러나 메시지 예약을 이해 하면 미리 정의 된 메시지 블록 형식의 동작을 보다 잘 이해할 수 있습니다.However, understanding message reservation can help you better understand the behavior of some of the predefined message block types.

Non-greedy 및 greedy 조인을 고려 합니다.Consider non-greedy and greedy joins. 이러한 두 가지 모두 메시지 예약을 사용 하 여 나중에 사용할 메시지를 예약 합니다.Both of these use message reservation to reserve messages for later use. 앞에서 설명한 것 처럼 non-greedy 조인은 두 단계로 메시지를 수신 합니다.A described earlier, a non-greedy join receives messages in two phases. 첫 번째 단계에서 non-greedy join 개체는 각 소스에서 메시지를 받을 때까지 대기 합니다.During the first phase, a non-greedy join object waits for each of its sources to receive a message. 그런 다음 non-greedy 조인은 각 메시지를 예약 하려고 시도 합니다.A non-greedy join then attempts to reserve each of those messages. 각 메시지를 예약할 수 있는 경우 모든 메시지를 사용 하 여 대상에 전파 합니다.If it can reserve each message, it consumes all messages and propagates them to its target. 그렇지 않으면 메시지 예약을 해제 하거나 취소 하 고 각 소스가 메시지를 받을 때까지 기다립니다.Otherwise, it releases, or cancels, the message reservations and again waits for each source to receive a message.

여러 소스에서 입력 메시지를 읽는 greedy 조인은 메시지 예약을 사용 하 여 각 소스에서 메시지를 수신 하기 위해 대기 하는 동안 추가 메시지를 읽습니다.A greedy join, which also reads input messages from a number of sources, uses message reservation to read additional messages while it waits to receive a message from each source. 예를 들어 메시지 블록 및에서 메시지를 수신 하는 greedy 조인을 고려 합니다 A B .For example, consider a greedy join that receives messages from message blocks A and B. Greedy 조인이 B의 메시지 두 개를 받지만에서 메시지를 아직 받지 않은 경우 A greedy 조인은에서 두 번째 메시지의 고유한 메시지 식별자를 저장 B 합니다.If the greedy join receives two messages from B but has not yet received a message from A, the greedy join saves the unique message identifier for the second message from B. Greedy 조인이에서 메시지를 수신 A 하 고 이러한 메시지를 전파 한 후에는 저장 된 메시지 식별자를 사용 하 여의 두 번째 메시지를 B 계속 사용할 수 있는지 확인 합니다.After the greedy join receives a message from A and propagates out these messages, it uses the saved message identifier to see if the second message from B is still available.

사용자 고유의 사용자 지정 메시지 블록 형식을 구현할 때 메시지 예약을 사용할 수 있습니다.You can use message reservation when you implement your own custom message block types. 사용자 지정 메시지 블록 형식을 만드는 방법에 대 한 예제는 연습: 사용자 지정 메시지 블록 만들기를 참조 하세요.For an example about how to create a custom message block type, see Walkthrough: Creating a Custom Message Block.

[맨 위로이동][Top]

참고 항목See also

비동기 에이전트 라이브러리Asynchronous Agents Library