如何使异步方法对任务类型通用 [英] How to make async method generic over Task type

查看:79
本文介绍了如何使异步方法对任务类型通用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题表面上与使用通用类型作为异步方法的返回类型非常相似.但是,他没有现实世界的使用场景,因此可以说明的是,您无法做到这一点.我从 Jon Skeet的答案和博客文章

My question is on the surface very similar to Using a generic type as a return type of an async method. However, he did not have a real world usage scenario and so all that could be stated is that you can't do that. I understand from Jon Skeet's answer to that question and from the blog post Why must async methods return Task? why it is not supported. The post discusses workarounds, but none of them apply to my use case.

我的问题是,鉴于我正在尝试做的事情,解决语言限制的最佳方法是什么?

在生产代码中,我们有一个重试方法,该方法采用 Func< Task> 并返回 Task .然后,我们还需要能够重试 TaskT> 函数.因此,我们将重试方法更改为(略有简化):

In production code, we had a retry method that takes a Func<Task> and returns Task. We then needed to be able to retry TaskT> functions as well. So we changed the retry method to (slightly simplified):

public static async T Retry<T>(Func<T> action) where T : Task
{
    for (var i = 0; ; i++)
    {
        try
        {
            return await action();
        }
        catch (Exception)
        {
            if (i >= 3)
                throw;
        }       
    }
}

编译器当然会报告错误异步方法的返回类型必须为空,任务或任务".是否可以在不编写方法的两个副本的情况下使 Retry Task Task< T> 一起使用?

The compiler of course reports the error "The return type of an async method must be void, Task or Task". Can I make Retry work with both Task and Task<T> without writing two copies of the method?

推荐答案

不,异步只是不支持.假冒的最简单选择是:

No, async just doesn't support that. The simplest option to fake it would be:

public static async Task<T> Retry<T>(Func<Task<T>> action)
{
    for (var i = 0; ; i++)
    {
        try
        {
            return await action();
        }
        catch (Exception)
        {
            if (i >= 3)
                throw;
        }       
    }
}

public static async Task Retry(Func<Task> action)
{
    Func<Task<int>> d = async () => { await action(); return 0; };
    await Retry(d);
}

这不涉及代码重复,但是当您调用非泛型版本时,您最终会面临大量的任务层.您可以将后者更改为:

That doesn't involve code duplication, but you do end up with an awful lot of layers of tasks on top of each other when you call the non-generic version. You could change the latter to:

public static Task Retry(Func<Task> action)
{
    Func<Task<int>> d = async () => { await action(); return 0; };
    return Retry(d);
}

然后它会实际上返回一个 Task< int> ,但是假设您的呼叫者不在乎,它确实会节省一些重定向.

Then it will actually return a Task<int>, but assuming your callers don't care, it does save one bit of redirection.

这篇关于如何使异步方法对任务类型通用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆