【问题标题】:How to make partial method async如何使部分方法异步
【发布时间】:2019-03-26 22:30:05
【问题描述】:

我有一个使用部分方法生成的代码

{
    ...
    partial void InterceptOperationCall(IOperationContext context);
    ...

    async Task SomeMethod()
    {
        InterceptOperationCall(cntx);
        await LongOperation(cntx);
    }
}

手写部分

{
    partial void InterceptOperationCall(IOperationContext context)
    {
    }
}

我需要在InterceptOperationCall 内部进行异步调用有没有人知道一些解决部分方法限制的方法?

换句话: 我想异步执行 InterceptOperationCall 并保证在长时间操作之前,同时我想在另一个文件中可选地声明此方法的主体。

UPD 作为我选择的解决方案:

  • 不使用生成的部分方法存根,并使用动态代理 (Castle.DynamicProxy) 进行包装并使用 AsyncInterceptorBase 来自 (Nito.AsyncEx)
  • 我看到的另一个选项是重写代码生成器

一直在寻找更好的解决方案的任何方式,如果有人知道另一种方法来提供可选的能力来使用 somoe 异步逻辑包装异步调用,请帮助我。

【问题讨论】:

  • 如果你想要异步部分方法的限制可以在文档中找到它们。但是,如果您需要解决部分方法限制,则需要提供更多信息。
  • @Llazar,感谢关注,我添加了我的问题的一些细节,你能告诉你需要什么信息吗?
  • @gabba 是您希望能够等待分部方法还是能够使用分部方法调用可等待函数?显示的示例是void 方法,所以我要求澄清。
  • 如果重写代码生成器是一种选择,那么我建议重写它以更符合 async-await API。
  • @Nkosi,你能提供一些样品或提供一个想法吗?

标签: c# asynchronous auto-generate


【解决方案1】:

部分方法就像接口。他们是合同。任何实现部分方法的人,就像接口方法一样,都在履行该契约。在这种情况下,方法的契约是同步方法。没有办法有一个异步实现,因为该方法的正确异步实现需要方法的调用者知道它是一个异步方法,并采取相应的行动。由于调用者已将合约编写为同步方法,因此不会发生这种情况。

因此,您的解决方案是将方法的合同更改为异步,这意味着更改部分方法的声明,或者提供同步而不是异步的实现。

我想第三种选择是让接口(在这种情况下,部分方法)支持两者。有两个部分方法,一个异步,一个同步,让实现提供他们想要的任何一个。

【讨论】:

  • 你能提供部分异步方法的例子吗?或者给我举个例子?
  • @gabba 它只是具有任何其他异步方法的签名。它会返回一个Task,或者以旧的编码风格,接受一个回调,或者使用一些其他的方式来通知调用者它已经完成了。但是现在它通常只会返回一个Task
  • 据我所知,部分方法无法返回值。部分方法必须是无效的。
  • @gabba 然后它必须接受回调,或者其他形式的异步,可以作为参数传递而不是由方法返回。
【解决方案2】:

我看不出有什么方法可以避免 async void 的所有缺点(正如 Peter Schneider 评论中链接的 Stephen Cleary 文章中所讨论的那样)

如果您找不到或无法编写相关异步 API 的同步版本,我认为您最好的选择是调用异步方法,然后使用 task.Wait() 等待完成。如果您有多个异步调用,请使用 ContinueWith 组合它们。本质上,您需要使用 .Net 4.0 风格的任务库。

【讨论】:

    【解决方案3】:

    在实现分部方法时可以使用 async 关键字。

    所以

    async partial void InterceptOperationCall(IOperationContext context) {
    
    }
    

    应该没问题。

    【讨论】:

    • 您能否在不知道相关代码的上下文(没有双关语)的情况下安全地建议async void
    • 不...我认为用户不知道如何为自动生成的方法连接异步实现。然而有gotchas需要照顾......
    • @PeterSchneider,太好了!它将编译并工作,但 InterceptOperationCall、LongOperation 方法的执行顺序取决于竞争条件。你知道一些方法可以让这个构造等待吗?
    • @gabba 当然,您返回 async Task 而不是 async void (现在您看到部分类和异步方法的问题)。您可能需要重新考虑您的设计以不再使用部分类。
    • @ScottChamberlain,我不得不使用部分代码,因为需要使用现有代码,你能用异步任务解释你的想法吗?
    猜你喜欢
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多