3

I am writing a Connection like class around an interop object. In particular, the closing of my connection is asynchronous.

The object I am interfacing with has a very poor API, like:

public interface InteropObject
{
    void StartLongTask();
    void IsLongTaskInProgress();
    void AbortLongTask();
}

All methods return immediately.

Here is the interface I ended up with:

public interface IConnection
{
    // [..]
    Task OpenAsync();
    Task RunOperationAsync();
    Task CloseAsync();
    // [..]
}

And the following implementation:

public class Connection : IConnection
{
    private InteropObject _myObject;

    Task OpenAsync()
    { // some required stuff }
    
    async Task RunOperationAsync()
    {
        _myObject.StartLongTask()
        while(_myObject.IsLongTaskInProgress())
        {
            await Task.Delay(TimeSpan.FromSeconds(1));
        }
    }

    async ask CloseAsync()
    {
        if(_myObject.IsLongTaskInProgress())
        {
            _myObject.AbortLongTask();
            // because the abort is not immediate, I have to wait until the end
            while(_myObject.IsLongTaskInProgress())
            {
                await Task.Delay(TimeSpan.FromSeconds(1));
            }
        }
    }
}

The problem I am facing is that I am a little bit confused about the approach to take, regarding the implementation or not of IDisposable along with IDisposableAsync. According to the MSDN:

It is typical when implementing the IAsyncDisposable interface that classes will also implement the IDisposable interface.

But in the MSDN exemple, the Utf8JsonWriter implements both a IDisposable and IDisposableAsync methods, which make the implementation of these interfaces easy in their example.

In my case, I do not have a synchronous cleanup operation. I don't want to implement such operation since I don't want the Close operation to return until the current operation is actually finished.

So, is okay to only implement IDisposableAsync ?

Or should I implement a synchronous Close method (that only calls _myObject.AbortLongTask();, or may be using an ugly Thread.Sleep() instead of Task.Delay()) and implement both IDisposable and IDisposableAsync?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
fharreau
  • 2,105
  • 1
  • 23
  • 46
  • _One of the key differences however, is that this implementation allows for asynchronous cleanup operations._ It depends, how are you going to use a `Connection` class. [This answer](https://stackoverflow.com/a/55678438/4728685) seems to be an exact thing what you want – Pavel Anikhouski Oct 29 '20 at 11:48
  • I updated my question to be clearer. I will implement the `IDisposableAsync` since this is how I want my `Connection` to be used. I understand the necessity to implement `IDisposable` for fallback cases and for finalization stuff (even if in my cases, I do not manipulate unmanaged object, so it is not an issue). But I don't like any of the option I have to implement a synchronous cleanup operation. So is it acceptable to not implement `IDisposable`? – fharreau Oct 29 '20 at 14:13
  • 1
    @fharreau: Yes, that's perfectly acceptable. In general, I advise people to ignore Microsoft's recommendation of the disposable pattern. – Stephen Cleary Dec 06 '20 at 17:36

0 Answers0