2

I am testing out the async functionality in WCF and noticed following strange behavior:

Having the following two methods in IService.cs

[OperationContract]
string LongRunningMethod(int timeout, string message);

[OperationContract]
Task<string> LongRunningMethodAsync(int timeout, string message);

and Service.cs

public string LongRunningMethod(int timeout, string message)
{
    Thread.Sleep(timeout);
    return message;
}

public async Task<string> LongRunningMethodAsync(int timeout, string message)
{
    await Task.Run(() => Thread.Sleep(timeout));
    return message;
}

I get the exception

An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll

Additional information: Cannot have two operations in the same contract with the same name, methods LongRunningMethodAsync and LongRunningMethod in type WcfService.IService violate this rule. You can change the name of one of the operations by changing the method name or by using the Name property of OperationContractAttribute.

as soon as the WCF attempt to open the service:

public Server()
{
    service = new Service("A fixed ctor test value that the service should return.");
    svh = new ServiceHost(service);
}

public void Open(string ipAdress, string port)
{
    svh.AddServiceEndpoint(
    typeof(IService),
    new NetTcpBinding(),
    "net.tcp://"+ ipAdress + ":" + port);
    svh.Open(); // exception is thrown here
}

If I rename LongRunningMethodAsync into LongRunningMethodAsyncNew I do not get the exception. On the client-side having the two functions LongRunningMethodAsync and LongRunningMethodAsync that call the respective server versions does not cause any issues:

public class Client : IMyEvents
{
    ChannelFactory<IService> scf;
    IService s;

    public void OpenConnection(string ipAddress, string port)
    {
        var binding = new NetTcpBinding();

        scf = new DuplexChannelFactory<IService>(
        new InstanceContext(this),
        binding,
        "net.tcp://" + ipAddress + ":" + port);
        s = scf.CreateChannel();
    }

    public string LongRunningMethod(int timeout, string message)
    {
        return s.LongRunningMethod(timeout, message);
    }

    public async Task<string> LongRunningMethodAsync(int timeout, string message)
    {
        return await s.LongRunningMethodAsyncNew(timeout, message);
    }
}

What is going on here?

Community
  • 1
  • 1
packoman
  • 1,230
  • 1
  • 16
  • 36
  • 1
    WCF automatically generates async versions of your methods. Have a look at [How to use Visual Studio - generated async WCF calls?](http://stackoverflow.com/questions/13777710/how-to-use-visual-studio-generated-async-wcf-calls) – stuartd Sep 08 '16 at 11:37
  • @stuartd Thanks for the answer. I am new to WCF and as far as I understand I am not generating the the service (not sure though). I am having trouble finding the service reference mentioned "service reference" as mentioned in your link and shown here: http://stackoverflow.com/questions/29407032/configure-service-reference-object-reference-is-not-set-to-an-instance-of-a So is there anyway I can disable the autogeneration? If I remove the the Async-version from the service, I get a compiler error, for the corresponding code in the `Client.cs` .... – packoman Sep 08 '16 at 11:54
  • @stuartd BTW: As you can see I am self-hosting and using channels to configure the service completely in code. If I understood correctly the service-references are present only if you autogenerate the service and use the XML-configuration(?). If you care to turn your comment into an answer, I would be happy accept it, once the last hurdle is taken .... – packoman Sep 08 '16 at 11:59
  • That's correct, the service reference is the client-side generated proxy. I'm don't know how or why [svcutil](https://msdn.microsoft.com/en-us/library/aa347733(v=vs.110).aspx) (that generates the async methods) gets involved with self-hosted services though. – stuartd Sep 08 '16 at 12:09
  • @stuartd svcutil isn't but *some* code has to generate the WSDL, XSD files that will be sent to the clients, map requests to methods etc. The convention is that an operation maps either to `OperationName` or `OperationNameAsync` unless a different name is specified in the attribute. `async` means that the **method** can use asynchronous calls, not that `WCF` will execute it asynchronously. Asynchronous execution is controlled by the service behavior and is probably asynchronous already – Panagiotis Kanavos Sep 08 '16 at 15:28
  • @packoman you don't need two methods. WCF itself controls if an *operation* runs in a separate thread and typically it does. That's controlled by the service behaviour's threading model. `async` only means that your *method* can use the `await` keyword. – Panagiotis Kanavos Sep 08 '16 at 15:30
  • @packoman, see if [this](http://stackoverflow.com/q/22623922/1768303) helps. – noseratio Sep 09 '16 at 11:26

0 Answers0