転送Transfer

このトピックでは、Windows Communication Foundation (WCF) アクティビティトレースモデルでの転送について説明します。This topic describes transfer in the Windows Communication Foundation (WCF) activity tracing model.

転送の定義Transfer Definition

アクティビティ間の転送は、エンドポイント内の関連アクティビティで発生したイベント間の因果関係を表します。Transfers between activities represent causal relationships between events in the related activities within endpoints. 制御が 2 つのアクティビティ間を流れる場合 (アクティビティの境界を越えたメソッド呼び出しなど)、転送によってこれらのアクティビティが関連付けられます。Two activities are related with transfers when control flows between these activities, for example, a method call crossing activity boundaries. WCF では、サービスでバイトが受信されると、メッセージオブジェクトが作成されたときに、受信側の受信アクティビティが Bytes Receive アクティビティに転送されます。In WCF, when bytes are incoming on the service, the Listen At activity is transferred to the Receive Bytes activity where the message object is created. エンドツーエンドのトレースシナリオの一覧と、それぞれのアクティビティとトレースの設計については、「エンドツーエンドのトレースのシナリオ」を参照してください。For a list of end-to-end tracing scenarios, and their respective activity and tracing design, see End-To-End Tracing Scenarios.

転送トレースを出力するには、次の構成コードのように、トレース ソースに ActivityTracing を設定します。To emit transfer traces, use the ActivityTracing setting on the trace source as demonstrated by the following configuration code.

<source name="System.ServiceModel" switchValue="Verbose,ActivityTracing">  

転送を使用したエンドポイント内でのアクティビティの関連付けUsing Transfer to Correlate Activities Within Endpoints

アクティビティと転送により、ユーザーはエラーの根本原因をほぼ突き止めることができます。Activities and transfers permit the user to probabilistically locate the root cause of an error. たとえば、コンポーネント M と N のアクティビティ M と N の間で、M から N および N から M への転送を行い、M への転送の直後に N でクラッシュが発生した場合、N から M にデータを返したことが原因でクラッシュが発生した可能性があるという結論を下すことができます。For example, if we transfer back and forth between activities M and N respectively in components M and N, and a crash happens in N right after the transfer back to M, we can draw the conclusion that it is likely due to N’s passing data back to M.

アクティビティ M とアクティビティ N の間に制御のフローが存在する場合、転送トレースは M から N に出力されます。たとえば、メソッド呼び出しがアクティビティの境界を越えるため、N が M に代わって何らかの処理を実行するとします。A transfer trace is emitted from activity M to activity N when there is a flow of control between M and N. For example, N performs some work for M because of a method call crossing the activities’ boundaries. N は既に存在する場合もあれば、作成されている場合もあります。N may already exist or has been created. N が、M に代わって何らかの処理を実行する新しいアクティビティである場合、N は M によって発生します。N is spawned by M when N is a new activity that performs some work for M.

M から N への転送の後に、N から M に転送することはできません。これは、M は N で処理を発生させることはできますが、N がその処理をいつ完了するかまでは追跡しないからです。A transfer from M to N may not be followed by a transfer back from N to M. This is because M can spawn some work in N and do not track when N completes that work. 実際、N がタスクを完了する前に M が終了する場合があります。In fact, M can terminate before N completes its task. これは、リスナーアクティビティ (N) を生成して終了する "Open ServiceHost" アクティビティ (M) で発生します。This happens in the "Open ServiceHost" activity (M) that spawns Listener activities (N) and then terminates. N から M への転送は、N が M に関連する処理を完了したことを意味します。A transfer back from N to M means that N completed the work related to M.

N は、M に関連しない他の処理を引き続き実行できます。たとえば、既存の認証システム アクティビティ (N) は、さまざまなログイン アクティビティからのログイン要求 (M) を受信し続けることができます。N can continue performing other processing unrelated to M, for example, an existing authenticator activity (N) that keeps receiving login requests (M) from different login activities.

アクティビティ M と N の間に、入れ子のリレーションシップが必ずしも存在するわけではありません。入れ子のリレーションシップが存在しない状況が発生する原因として、2 つのケースが考えられます。A nesting relationship does not necessarily exist between activities M and N. This can happen due to two reasons. 1 つは、アクティビティ M が アクティビティ N を開始したが、N で実行される実際の処理を M が監視しない場合です。もう 1 つは、N が既に存在する場合です。First, when activity M does not monitor the actual processing performed in N although M initiated N. Second, when N already exists.

転送の例Example of Transfers

転送の 2 つの例を次に示します。The following lists two transfer examples.

  • サービス ホストの作成時に、コンストラクターは呼び出し元のコードから制御を取得します。つまり、呼び出し元のコードがコンストラクターに転送されます。When you create a service host, the constructor gains control from the calling code, or the calling code transfers to the constructor. コンストラクターは、必要な処理を終えると、呼び出し元に制御を返します。つまり、コンストラクターから呼び出し元への逆転送が起こります。When the constructor has finished executing, it returns control to the calling code, or the constructor transfers back to the calling code. これは、入れ子になったリレーションシップの例です。This is the case of a nested relationship.

  • リスナーはトランスポート データの処理を開始するときに、新しいスレッドを作成し、"バイトを受信" アクティビティに、処理の適切なコンテキストとして制御とデータを渡します。When a listener starts processing transport data, it creates a new thread and hands to the Receive Bytes activity the appropriate context for processing, passing control and data. このスレッドが要求の処理を完了しても、"バイトを受信" アクティビティからリスナーには何も渡されません。When that thread has finished processing the request, the Receive Bytes activity passes nothing back to the listener. この場合、新しいスレッドのアクティビティへの転送はありますが、このアクティビティからの転送はありません。In this case, we have a transfer in but no transfer out of the new thread activity. 2 つのアクティビティは関連していますが、入れ子にはなっていません。The two activities are related but not nested.

アクティビティ転送シーケンスActivity Transfer Sequence

適切なアクティビティ転送シーケンスには、次の手順が含まれます。A well-formed activity transfer sequence includes the following steps.

  1. 新しい gAId を選択して、新しいアクティビティを開始します。Begin a new activity, which consists of selecting a new gAId.

  2. 現在のアクティビティ ID から新しい gAId への転送トレースを出力します。Emit a transfer trace to that new gAId from the current activity ID

  3. TLS に新しい ID を設定します。Set the new ID in TLS

  4. Start トレースを出力して、新しいアクティビティの開始を示します。Emit a start trace to indicate the beginning of the new activity by.

  5. 次の手順を実行して、元のアクティビティに戻ります。Return to the original activity consists of the following:

  6. 元の gAId への転送トレースを出力します。Emit a transfer trace to the original gAId

  7. Stop トレースを出力して、新しいアクティビティの終了を示します。Emit a Stop trace to indicate the end of the new activity

  8. TLS を以前の gAId に設定します。Set TLS to the old gAId.

これを実行する方法を次のコード例に示します。The following code example demonstrates how to do this. この例は、新しいアクティビティへの転送時にブロック呼び出しが行われることを想定しており、Suspend トレースと Resume トレースが含まれています。This sample assumes a blocking call is made when transferring to the new activity, and includes suspend/resume traces.

// 0. Create a trace source  
TraceSource ts = new TraceSource("myTS");  

// 1. remember existing ("ambient") activity for clean up  
Guid oldGuid = Trace.CorrelationManager.ActivityId;  
// this will be our new activity  
Guid newGuid = Guid.NewGuid();

// 2. call transfer, indicating that we are switching to the new AID  
ts.TraceTransfer(667, "Transferring.", newGuid);  

// 3. Suspend the current activity.  
ts.TraceEvent(TraceEventType.Suspend, 667, "Suspend: Activity " + i-1);  

// 4. set the new AID in TLS  
Trace.CorrelationManager.ActivityId = newGuid;  

// 5. Emit the start trace  
ts.TraceEvent(TraceEventType.Start, 667, "Boundary: Activity " + i);  

// trace something  
ts.TraceEvent(TraceEventType.Information, 667, "Hello from activity " + i);  

// Perform Work  
// some work.  
// Return  
ts.TraceEvent(TraceEventType.Information, 667, "Work complete on activity " + i);

// 6. Emit the transfer returning to the original activity  
ts.TraceTransfer(667, "Transferring Back.", oldGuid);  

// 7. Emit the End trace  
ts.TraceEvent(TraceEventType.Stop, 667, "Boundary: Activity " + i);  

// 8. Change the tls variable to the original AID  
Trace.CorrelationManager.ActivityId = oldGuid;

// 9. Resume the old activity  
ts.TraceEvent(TraceEventType.Resume, 667, "Resume: Activity " + i-1);  

関連項目See also