[c#] 인터페이스 구현을 비동기로 만들기

현재 일부 비동기 메서드를 사용하여 응용 프로그램을 만들려고합니다. 내 모든 IO는 인터페이스의 명시 적 구현을 ​​통해 수행되며 작업을 비 동기화하는 방법에 대해 약간 혼란 스럽습니다.

내가 보는 것처럼 구현에는 두 가지 옵션이 있습니다.

interface IIO
{
    void DoOperation();
}

OPTION1 :
암시 적 구현 비동기를 수행하고 암시 적 구현의 결과를 기다립니다.

class IOImplementation : IIO
{

     async void DoOperation()
    {
        await Task.Factory.StartNew(() =>
            {
                //WRITING A FILE OR SOME SUCH THINGAMAGIG
            });
    }

    #region IIO Members

    void IIO.DoOperation()
    {
        DoOperation();
    }

    #endregion
}

OPTION2 :
명시 적 구현 비동기를 수행하고 암시 적 구현에서 작업을 기다립니다.

class IOAsyncImplementation : IIO
{
    private Task DoOperationAsync()
    {
        return new Task(() =>
            {
                //DO ALL THE HEAVY LIFTING!!!
            });
    }

    #region IIOAsync Members

    async void IIO.DoOperation()
    {
        await DoOperationAsync();
    }

    #endregion
}

이러한 구현 중 하나가 다른 것보다 낫거나 내가 생각하지 않는 다른 방법이 있습니까?



답변

이러한 옵션 중 어느 것도 올바르지 않습니다. 비동기식으로 동기 인터페이스를 구현하려고합니다. 그러지 마. 문제는 DoOperation()돌아올 때 작업이 아직 완료되지 않는다는 것입니다. 더 나쁜 것은 작업 중에 예외가 발생하면 (IO 작업에서 매우 일반적 임) 사용자는 해당 예외를 처리 할 기회가 없습니다.

해야 할 일은 인터페이스수정하여 비동기식으로 만드는 것입니다.

interface IIO
{
    Task DoOperationAsync(); // note: no async here
}

class IOImplementation : IIO
{
    public async Task DoOperationAsync()
    {
        // perform the operation here
    }
}

이렇게하면 사용자는 작업이 진행 async되고 있음을 알 수 있으며 작업을 수행 할 수 await있습니다. 이것은 또한 코드 사용자가로 전환하도록 강요 async하지만 피할 수 없습니다.

또한 StartNew()구현에서 사용 하는 것이 예일 뿐이라고 가정 하므로 비동기 IO를 구현하는 데 필요하지 않습니다. ( new Task()더 나쁜 것은 작동하지 않을 Start()Task입니다..)


답변

더 나은 솔루션은 비동기 작업을위한 또 다른 인터페이스를 도입하는 것입니다. 새 인터페이스는 원래 인터페이스에서 상속되어야합니다.

예:

interface IIO
{
    void DoOperation();
}

interface IIOAsync : IIO
{
    Task DoOperationAsync();
}


class ClsAsync : IIOAsync
{
    public void DoOperation()
    {
        DoOperationAsync().GetAwaiter().GetResult();
    }

    public async Task DoOperationAsync()
    {
        //just an async code demo
        await Task.Delay(1000);
    }
}


class Program
{
    static void Main(string[] args)
    {
        IIOAsync asAsync = new ClsAsync();
        IIO asSync = asAsync;

        Console.WriteLine(DateTime.Now.Second);

        asAsync.DoOperation();
        Console.WriteLine("After call to sync func using Async iface: {0}",
            DateTime.Now.Second);

        asAsync.DoOperationAsync().GetAwaiter().GetResult();
        Console.WriteLine("After call to async func using Async iface: {0}",
            DateTime.Now.Second);

        asSync.DoOperation();
        Console.WriteLine("After call to sync func using Sync iface: {0}",
            DateTime.Now.Second);

        Console.ReadKey(true);
    }
}

PS 비동기 작업을 다시 설계하여 실제로 void를 반환해야하는 경우가 아니라면 void 대신 Task를 반환합니다.


답변