Rychoc
Rychoc

Reputation: 23

WCF Task based asynchronous callback

I have created WCF service in VS2015:

[ServiceContract(CallbackContract = typeof(IMyCallback))]
public interface IMyService { }

IMyCallback looks like:

[ServiceContract]
public interface IMyCallback {

[OperationContract]
Task<string> OnServerEvent(UserAppEventData evData);

I've built the server, run it, then added service reference (by right click on solution explorer).
The client object is defined as

 [CallbackBehaviorAttribute(
     ConcurrencyMode = ConcurrencyMode.Reentrant,
     IncludeExceptionDetailInFaults = true,
     UseSynchronizationContext = true,
     ValidateMustUnderstand = true
)]
public class QMyClient : IMyCallback { }

Automatically generated interface implementation made method in sync manner:

public string OnServerEvent(UserAppEventData evData) { }

This code does't work (and isn't asynchronous) and hangs client at OnServerEvent.

When I changed code manuallly to

public async Task<string> OnServerEvent(UserAppEventData evData)

and have done the same in auto generated "service references\...\Reference.cs, all works fine. But I don't want to change Referenece.cs every time I'm updating Service Reference.

Is there any method to force "Update Service Reference" make TBA OperationContractAttribute on callback?

At ordinary WCF service direction everything works OK, VS generates task based operations.

Upvotes: 2

Views: 1128

Answers (2)

Rohit Garg
Rohit Garg

Reputation: 493

What @VMAtm suggested will work out just fine.

I think, you could also use ChannelFactory for this scenario. It is very flexible and you can then await on the service operations from client side. Additional benefit, you don't need to modify client when there are these kind of changes on service side.

Something like:

var channelFactory = new ChannelFactory<IService>(
                    "WSHttpBinding_IService" // endpoint name
                    ); 

IService channel = channelFactory.CreateChannel();

string result = await channel.OnServerEvent();

Console.WriteLine(result);

Please note that for this scenario, you will have to import common interface library to client side as dll because then it will need to know about contracts and data contracts.

Upvotes: 1

VMAtm
VMAtm

Reputation: 28355

By default the service reference you've added to solution doesn't have asynchronous operations, but you can enable them and decide which option you use for your async methods - task-based or old-fashion asynchronous. This option is available in Advanced settings for service reference.

enter image description here

If you're using a svcutil tool, it will create the task-based methods by default, however, you can change that behavior by some flags like /async or /syncOnly.

Upvotes: 2

Related Questions