Sdílet prostřednictvím


Korelace trvanlivého duplexního přenosu

Odolná duplexní korelace, označovaná také jako korelace zpětného volání, je užitečná, když má služba pracovního postupu požadavek na odeslání zpětného volání počátečnímu volajícímu. Na rozdíl od duplexního prostředí WCF může zpětné volání probíhat kdykoli v budoucnu a není svázané se stejným kanálem nebo životností kanálu. Jediným požadavkem je, aby volající měl aktivní koncový bod, který naslouchá zprávě zpětného volání. To umožňuje dvěma službám pracovních postupů komunikovat v dlouhotrvající konverzaci. Tento článek obsahuje přehled trvalé duplexní korelace.

Použití odolné duplexní korelace

Aby bylo možné používat odolnou duplexní korelaci, musí tyto dvě služby používat vazbu s podporou kontextu, která podporuje obousměrné operace, jako NetTcpContextBinding je například .WSHttpContextBinding Volající služba zaregistruje ClientCallbackAddress na svém klientovi Endpointpožadovanou vazbu . Přijímající služba obdrží tato data v počátečním volání a pak je použije samostatně Endpoint v Send aktivitě, která provádí volání zpět do volající služby. V tomto příkladu spolu komunikují dvě služby. První služba vyvolá metodu druhé služby a pak čeká na odpověď. Druhá služba zná název metody zpětného volání, ale koncový bod služby, která implementuje tuto metodu, není v době návrhu znám.

Poznámka:

Trvalý duplexní protokol lze použít pouze v případech AddressingVersion , kdy je koncový bod nakonfigurovaný WSAddressing10. Pokud tomu tak není, InvalidOperationException vyvolá se výjimka s následující zprávou: "Zpráva obsahuje hlavičku kontextu zpětného volání s odkazem na koncový bod pro AddressingVersion. Kontext zpětného volání lze přenášet pouze v případech, kdy je nakonfigurováno "WSAddressing10".

V následujícím příkladu je služba pracovního postupu hostována, která vytvoří zpětné Endpoint volání pomocí WSHttpContextBinding.

// Host WF Service 1.
string baseAddress1 = "http://localhost:8080/Service1";
WorkflowServiceHost host1 = new WorkflowServiceHost(GetWF1(), new Uri(baseAddress1));

// Add the callback endpoint.
WSHttpContextBinding Binding1 = new WSHttpContextBinding();
host1.AddServiceEndpoint("ICallbackItemsReady", Binding1, "ItemsReady");

// Add the service endpoint.
host1.AddServiceEndpoint("IService1", Binding1, baseAddress1);

// Open the first workflow service.
host1.Open();
Console.WriteLine("Service1 waiting at: {0}", baseAddress1);

Pracovní postup, který implementuje tuto službu pracovního postupu, inicializuje korelaci zpětného volání s jeho Send aktivitou a odkazuje na tento koncový bod zpětného volání z aktivity, která koreluje s aktivitou ReceiveSend. Následující příklad představuje pracovní postup vrácený z GetWF1 metody.

Variable<CorrelationHandle> CallbackHandle = new Variable<CorrelationHandle>();

Receive StartOrder = new Receive
{
    CanCreateInstance = true,
    ServiceContractName = "IService1",
    OperationName = "StartOrder"
};

Send GetItems = new Send
{
    CorrelationInitializers =
    {
        new CallbackCorrelationInitializer
        {
            CorrelationHandle = CallbackHandle
        }
    },
    ServiceContractName = "IService2",
    OperationName = "StartItems",
    Endpoint = new Endpoint
    {
        AddressUri = new Uri("http://localhost:8081/Service2"),
        Binding = new WSHttpContextBinding
        {
            ClientCallbackAddress = new Uri("http://localhost:8080/Service1/ItemsReady")
        }
    }
};

Receive ItemsReady = new Receive
{
    ServiceContractName = "ICallbackItemsReady",
    OperationName = "ItemsReady",
    CorrelatesWith = CallbackHandle,
};

Activity wf = new Sequence
{
    Variables =
    {
        CallbackHandle
    },
    Activities =
    {
        StartOrder,
        new WriteLine
        {
            Text = "WF1 - Started"
        },
        GetItems,
        new WriteLine
        {
            Text = "WF1 - Request Submitted"
        },
        ItemsReady,
        new WriteLine
        {
            Text = "WF1 - Items Received"
        }
     }
};

Druhá služba pracovního postupu je hostovaná pomocí kontextové vazby poskytované systémem.

// Host WF Service 2.
string baseAddress2 = "http://localhost:8081/Service2";
WorkflowServiceHost host2 = new WorkflowServiceHost(GetWF2(), new Uri(baseAddress2));

// Add the service endpoint.
WSHttpContextBinding Binding2 = new WSHttpContextBinding();
host2.AddServiceEndpoint("IService2", Binding2, baseAddress2);

// Open the second workflow service.
host2.Open();
Console.WriteLine("Service2 waiting at: {0}", baseAddress2);

Pracovní postup, který implementuje tuto službu pracovního postupu, začíná aktivitou Receive . Tato aktivita příjmu inicializuje korelaci zpětného volání pro tuto službu, zpoždění po dobu, která simuluje dlouhotrvající práci, a pak volá zpět do první služby pomocí kontextu zpětného volání, který byl předán při prvním volání do služby. Následující příklad představuje pracovní postup vrácený voláním GetWF2. Aktivita Send má zástupnou adresu http://www.contoso.com; skutečná adresa použitá za běhu je zadaná adresa zpětného volání.

Variable<CorrelationHandle> ItemsCallbackHandle = new Variable<CorrelationHandle>();

Receive StartItems = new Receive
{
    CorrelationInitializers =
    {
        new CallbackCorrelationInitializer
        {
            CorrelationHandle = ItemsCallbackHandle
        }
    },
    CanCreateInstance = true,
    ServiceContractName = "IService2",
    OperationName = "StartItems"
};

Send ItemsReady = new Send
{
    CorrelatesWith = ItemsCallbackHandle,
    Endpoint = new Endpoint
    {
        // The callback address on the binding is used
        // instead of this placeholder address.
        AddressUri = new Uri("http://www.contoso.com"),

        Binding = new WSHttpContextBinding()
    },
    OperationName = "ItemsReady",
    ServiceContractName = "ICallbackItemsReady"
};

Activity wf = new Sequence
{
    Variables =
    {
        ItemsCallbackHandle
    },
    Activities =
    {
        StartItems,
        new WriteLine
        {
            Text = "WF2 - Request Received"
        },
        new Delay
        {
            Duration = TimeSpan.FromMinutes(90)
        },
        new WriteLine
        {
            Text = "WF2 - Sending items"
        },
        ItemsReady,
        new WriteLine
        {
            Text = "WF2 - Items sent"
        }
     }
};

StartOrder Při vyvolání metody v prvním pracovním postupu se zobrazí následující výstup, který ukazuje tok provádění prostřednictvím dvou pracovních postupů.

Service1 waiting at: http://localhost:8080/Service1
Service2 waiting at: http://localhost:8081/Service2
Press enter to exit.
WF1 - Started
WF2 - Request Received
WF1 - Request Submitted
WF2 - Sending items
WF2 - Items sent
WF1 - Items Received

V tomto příkladu oba pracovní postupy explicitně spravují korelaci pomocí CallbackCorrelationInitializer. Vzhledem k tomu, že v těchto ukázkových pracovních postupech byla pouze jedna korelace, byla by výchozí CorrelationHandle správa dostatečná.