[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를 반환합니다.