2

Let me start from some code. I have an asynchronous data channel :

interface IChannel
{
    Task<byte[]> SendRecv(string command, byte[] request);
}

and synchronous interface that describe operations that can be performed on a remote server:

interface IRemoteServer
{
    int DoLongTask(int param);
}

along with its implementation that uses the asynchronous data channel:

class RemoteServer : IRemoteServer
{
    private IChannel _channel;

    public int DoLongTask(int param)
    {
        var request = BitConverter.GetBytes(param);
        var response = _channel.SendRecv(nameof(DoLongTask), request).Result;
        return BitConverter.ToInt32(response, 0);
    }
}

and finally the application that was written asynchronously and uses the remote server abstraction:

class Application
{
    private IRemoteServer _server;

    async Task<int> SomeMethod(int param)
    {
        return await Task.Run(() => _server.DoLongTask(param));
    }
}

The problem of above code is that despite both the channel and application was written asynchronously, it blocks the thread-pool thread when accessing the Result in remote server implementation. Let's assume that IRemoteServer is immutable because its used in other places and I don't have a direct control how it looks. Now, when implementing the interface (class RemoteServer) I can't use the async word because C# assumes it's plain synchronous method - on the other hand I know that when executing the method I am already in a task so in theory I could use async in runtime to join both tasks (Application.SomeMethod and IChannel.SendRecv).

I'm looking for the solution to this problem (including low-level/advanced hacks), any help appreciated!

vnd
  • 356
  • 1
  • 6
  • 1
    Change the `IRemoteServer` interface methods from `int` to `Task`. If you have async stuff, it has to be async all the way down (and up). – Oliver Nov 29 '18 at 08:59
  • Possible duplicate of [How to call asynchronous method from synchronous method in C#?](https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c) – Liam Nov 29 '18 at 09:04
  • Yes, that's the most intuitive approach but I can't. I don't have the control over `IRemoteServer` interface that is provided by the library and used in synchronous way by other applications. – vnd Nov 29 '18 at 09:04
  • There's no simple fix without being able to change the interface. The call to `DoLongTask` cannot "release" the thread it's executing on in any way because the usual way for a method to do so is to *return to the caller* (with a `Task` or other awaitable representing the ongoing work that will complete later). But you can't return here whilst you a) Have further work to do and b) Don't know the correct value to return yet. – Damien_The_Unbeliever Nov 29 '18 at 09:28
  • You may want to use a semaphore like WaitOne. See : https://learn.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-client-socket-example – jdweng Nov 29 '18 at 10:06

0 Answers0