首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使接口实现异步

使接口实现异步
EN

Stack Overflow用户
提问于 2013-01-22 20:27:45
回答 4查看 136.1K关注 0票数 146

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

在我看来,我在实现中有两种选择:

代码语言:javascript
复制
interface IIO
{
    void DoOperation();
}

OPTION1:执行隐式异步实现,并等待隐式实现的结果。

代码语言:javascript
复制
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:异步执行显式实现,并等待来自隐式实现的任务。

代码语言:javascript
复制
class IOAsyncImplementation : IIO
{
    private Task DoOperationAsync()
    {
        return new Task(() =>
            {
                //DO ALL THE HEAVY LIFTING!!!
            });
    }

    #region IIOAsync Members

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

    #endregion
}

这些实现中是否有一种比另一种更好,或者是否有其他我没有考虑到的方法?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-22 21:00:02

这两个选项都不正确。您正在尝试异步实现同步接口。别干那事。问题是,当DoOperation()返回时,操作还没有完成。更糟糕的是,如果在操作过程中发生异常(这在IO操作中非常常见),用户将没有机会处理该异常。

您需要做的是修改接口,以便它是异步的:

代码语言:javascript
复制
interface IIO
{
    Task DoOperationAsync(); // note: no async here
}

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

这样,用户将看到操作是async,并且他们将能够对其执行await操作。这也迫使您的代码用户切换到async,但这是不可避免的。

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

票数 276
EN

Stack Overflow用户

发布于 2017-04-06 00:07:42

更好的解决方案是为异步操作引入另一个接口。新接口必须从原始接口继承。

示例:

代码语言:javascript
复制
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);
    }
}

附注:重新设计你的异步操作,让它们返回Task而不是void,除非你真的必须返回void。

票数 28
EN

Stack Overflow用户

发布于 2021-07-10 05:01:53

我根据Svick的回答创建了一个示例应用程序,并发现在不使用async关键字的情况下调用IOImplementation.DoOperationAsync()不会导致编译器/Visual Studio警告。这基于Visual Studio2019和.NET Core3.1。

下面是示例代码。

代码语言:javascript
复制
public interface ISomething
{
    Task DoSomethingAsync();
}
代码语言:javascript
复制
public class Something : ISomething
{
    public async Task DoSomethingAsync()
    {
        await Task.Run(() => Thread.Sleep(2000));
        Console.WriteLine("Message from DoSomethingAsync");

        throw new Exception("Some exception");
    }
}
代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        ISomething something = new Something();
        
        Console.WriteLine("pre something.DoSomethingAsync() without await");
        something.DoSomethingAsync(); // No compiler warning for missing "await" and exception is "swallowed"
        Console.WriteLine("post something.DoSomethingAsync() without await");

        Thread.Sleep(3000);

        // Output:
        // pre something.DoSomethingAsync() without await
        // post something.DoSomethingAsync() without await
        // Message from DoSomethingAsync
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14458566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档