When the callback mode is applied in WCF, it is recommended that the message exchange pattern of operation in callback contract be set to isoneway.
Of course, when the service calls callback and does not need to obtain the return value of callback from the client instance, it is the best choice to set MEP to isoneway. However, in some application scenarios, when we need to obtain the client callback result, we cannot set MEP to isoneway = true.
Of course, when MEP is set to isoneway = false, other synchronization settings must match, that is, the concurrentmode can only be reentrant or multiple.
The following shows a simple application mode: online real-time voting.
Its simple system model is as follows:
The WCF Service provides a simple voting service that collects the voting results and obtains the results of each client through the callback mechanism. Then, it returns the results to the service, and the WCF Service provides statistics.
For such a Voting Model, note the following when setting the service:
1. Operation in callback contract must be set to isoneway = false. Otherwise, callback cannot return to the server.
2. concurrentmode cannot be set to single, but only reentrant or multiple.
3. When the service callbacks client is used, the processing right of the callback result is in the service, for example, statistical processing of the result.
The main source code is given below:
Definition of callback contract and service contract
Using System;
Using System. Collections. Generic;
Using System. LINQ;
Using System. text;
Using System. servicemodel;
namespace wcfcallback
{< br> [servicecontract]
Public interface icaculatorcallback
{< br> [operationcontract]
int equals ( int result);
}
[servicecontract (callbackcontract = typeof (icaculatorcallback)]
Public interface icaculatorservice
{< br> [operationcontract]
void addto ( int N);
[Operationcontract]
VoidRegister ();
}
}
Servicecontract implementation and message Publishing
Using System;
Using System. Collections. Generic;
Using System. LINQ;
Using System. text;
Using System. servicemodel;
NamespaceWcfcallback
{
Public ClassAddeventagrs: eventargs
{
Public IntResult;
}
[Servicebehavior (concurrencymode = Concurrencymode. reentrant)]
Class Caculatorservice: icaculatorservice
{
Public Delegate Void Addeventhandler ( Object Sender, addeventagrs E );
Public Static Event Addeventhandler onaddcompleted;
Public Icaculatorcallback callback;
Public Int Result;
PublicCaculatorservice ()
{
Result= 0;
Console. writeline ("A calculator instance is constructed");
}
Public Void Register ()
{
Callback = System. servicemodel. operationcontext. Current. getcallbackchannel < Icaculatorcallback > ();
Onaddcompleted + = New Addeventhandler (caculatorservice_onaddcompleted );
}
Void Caculatorservice_onaddcompleted ( Object Sender, addeventagrs E)
{
Console. writeline ( " The onadd event has been triggered " );
Console. writeline ( " The callback result from client is " + Callback. Equals (E. Result ));
}
Public Void Broadaddevent (addeventagrs E, addeventhandler temp)
{
If (Onaddcompleted ! = Null )
{
Foreach (Addeventhandler Handler In Temp. getinvocationlist ())
{
Handler. begininvoke ( This , E, Null , Null );
}
}
}
Public Void Addto ( Int N)
{
Addeventagrs E = New Addeventagrs ();
This . Result + = N;
E. Result = Result;
Broadaddevent (E, onaddcompleted );
}
}
}
Implementation of Client1 callback:
Using System;
Using System. Collections. Generic;
Using System. LINQ;
Using System. text;
Namespace Wcfclient
{
Class Callback: icaculatorservicecallback
{
Public Int Equals ( Int N)
{
// Console. writeline ("Haha ");
Console. writeline ( " This callback is implemented on client, the callback result is {0} " , N. tostring ());
Return 2 * N;
}
}
}
Client2 callback implementation
Using System;
Using System. Collections. Generic;
Using System. LINQ;
Using System. text;
Namespace Wcfclient
{
Class Callback: icaculatorservicecallback
{
Public Int Equals ( Int N)
{
Console. writeline ( " I have received a broadcasting news, the callback result is {0} " , N. tostring ());
System. Threading. thread. Sleep ( 2000 );
Return N * N;
}
}
}
Running result:
Service screenshot
Client1 screenshot
Client 2 screenshot