使接口实现asynchronous

我目前正在尝试使用一些Async方法使我的应用程序。 我所有的IO都是通过一个接口的显式实现完成的,我对如何使这个操作asynchronous有点困惑。

正如我看到的事情,我有两个select在实施:

interface IIO { void DoOperation(); } 

选项1:执行隐式实现asynchronous并等待隐式实现中的结果。

 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 } 

选项2:执行显式实现asynchronous并等待隐式实现中的任务。

 class IOAsyncImplementation : IIO { private Task DoOperationAsync() { return new Task(() => { //DO ALL THE HEAVY LIFTING!!! }); } #region IIOAsync Members async void IIO.DoOperation() { await DoOperationAsync(); } #endregion } 

这些实现中的一个比另一个更好,还是有另外一种我没有想到的方式?

这些选项都不正确。 你正试图asynchronous实现一个同步接口。 不要这样做。 问题是,当DoOperation()返回时,操作还不完整。 更糟糕的是,如果在操作过程中发生exception(IO操作非常常见),用户将没有机会处理该exception。

你需要做的是修改接口 ,以便它是asynchronous的:

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

这样,用户将看到操作是async ,他们将能够await它。 这也迫使你的代码的用户切换到async ,但这是不可避免的。

另外,我假定在你的实现中使用StartNew()只是一个例子,你不应该需要这个来实现asynchronousIO。 ( new Task()更糟糕,甚至不能工作,因为你没有Start() Task 。)

更好的解决scheme是引入另一个asynchronous操作接口。 新界面必须从原始界面inheritance。

例:

 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重新devise你的asynchronous操作,让他们返回任务,而不是无效的,除非你真的必须返回无效。