【问题标题】:Is marking an interface method as async the right thing todo in my case在我的情况下,将接口方法标记为异步是正确的做法吗
【发布时间】:2013-11-05 21:37:53
【问题描述】:

我正在使用一个自定义框架,该框架在我的公司内使用了很长时间。 我想在我的代码中使用新的异步功能。

为了做到这一点,我必须将“MyClass”的“ProcessRequestMessage”标记为异步。 我无法更改接口“IFramework”和类“FrameworkBase”。

框架已经期望“ProcessRequestMessage”异步完成,所以我不必在方法结束时使用“Wait()”。 对“SetResponseCode”的调用向框架发出信号以完成“MyClass”的实例

问题: 我在异步功能的文档中读到,只有 void 事件应该被标记为异步以进入异步工作流(任务不适用于此处)。我的代码要求我将 void 接口方法的实现标记为入口点。

我可以这样做吗:

interface IFramework
{
    void ProcessRequestMessage()

    void SetResponseCode(int code)
}

public abstract class FrameworkBase: IFramework
{
    abstract void ProcessRequestMessage()

    public void SetResponseCode(int code)
    {
        //internal implementation
    }
}

public class MyClass: FrameworkBase
{

    protected override async void ProcessRequestMessage()
    {
        //await something

        SetResponseCode(0);
    }
}

【问题讨论】:

    标签: c# asynchronous async-await c#-5.0


    【解决方案1】:

    避免async void的主要原因有两个:

    1. 调用代码假定方法在返回时已完成。
    2. 它如何处理异常。

    在您的特定情况下,调用代码确实假设ProcessRequestMessage返回时操作已完成,因此您可以使用async void,但您必须非常小心你的例外。 (我更喜欢使用任务延续而不是async void)。

    我建议为此写一个FrameworkTaskBase

    public class FrameworkTestBase: FrameworkBase
    {
      protected abstract Task ProcessRequestMessageAsync();
      protected override sealed void ProcessRequestMessage()
      {
        ProcessRequestMessageAsync().ContinueWith(t =>
        {
          if (t.IsFaulted || t.IsCanceled)
            SetResponseCode(-1);
          else
            SetResponseCode(0);
        });
      }
    }
    
    public class MyClass: FrameworkBase
    {
      protected override async Task ProcessRequestMessageAsync()
      {
        //await something
      }
    }
    

    或者(使用async void):

    public class FrameworkTestBase: FrameworkBase
    {
      protected abstract Task ProcessRequestMessageAsync();
      protected override sealed async void ProcessRequestMessage()
      {
        try
        {
          await ProcessRequestMessageAsync();
          SetResponseCode(0);
        }
        catch
        {
          SetResponseCode(-1);
        }
      }
    }
    

    【讨论】:

    • OP 提到他们需要 async 来支持他们自己的自定义框架,我得到的印象是 Task/Task<T> 的概念甚至没有出现。
    • async 的自然返回类型为TaskTask<T>voidasync 的非自然返回类型。所以,Task 的本质是async
    • 我同意,但是,鉴于这是要与一些自定义框架一起使用,我会说这有点例外。
    • @StephenCleary 我最终使用了您发布的“替代方案”。我知道在这种情况下要特别注意例外情况。所以我想我涵盖了你的两个观点。如果异步功能的语言设计者完全禁止将 void 与异步一起使用,可能会更好。这将迫使开发人员编写更多代码,但至少异常不会那么容易泄漏(在任务属性中涵盖)。还是谢谢。
    • @rudimenter:最初设计async/await 功能时,它不包括对async void 的支持。它后来被添加(不顾语言团队的反对)以启用异步事件处理程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 2016-08-30
    相关资源
    最近更新 更多