C# 异步lamda应该在异步函数中运行吗?

C# 异步lamda应该在异步函数中运行吗?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,因此,除了Set或Delete之外,我还有以下代码和其他一些方法,但为了简单起见,我将保持简短: public byte[] Get(string key) { byte[] Action() => this.Cache.Get(key); return this.Execute(Action); } public void Delete(string key) { void Action() => this.Cache.Delete(key);

因此,除了Set或Delete之外,我还有以下代码和其他一些方法,但为了简单起见,我将保持简短:

public byte[] Get(string key)
{
    byte[] Action() => this.Cache.Get(key);
    return this.Execute(Action);
} 

public void Delete(string key)
{
    void Action() => this.Cache.Delete(key);
    return this.Execute(Action);
}

private void Execute(Action action)
{
    this.Execute(() =>
    {
        action();
        return 0;
    });
}

private T Execute<T>(Func<T> action)
{
    if (someCondition)
    {
        try
        {
            return action();
        }
        catch (Exception)
        {
            //do something
        }
    }
    else
    {
        //do something else
    }

    return default(T);
}
是异步还是同步


附加问题:有没有办法测试某个东西是否异步运行?我可以手动验证代码的“异步性”的一种方法,因此首先要介绍的是,异步的方法并不意味着“它上面有
async
关键字”。当方法很快返回调用方时,它是异步的,然后在返回给调用者并允许调用者继续做它想做的任何事情之后,完成要求它执行的任何操作。通常,这还涉及调用方以某种方式知道操作何时完成,是否成功,有时还包括操作的某些结果

async
关键字所做的只是允许该方法包含
wait
关键字。如果您没有将方法标记为a
async
,它就不知道
await
的任何用法实际上是否只有常规变量名,而不是一个特殊的关键字。
await
所做的是,您希望该方法在等待的任务完成后,安排在
await
之后运行的任何代码

记住这一点,我们可以检查您的方法,看看它们在做什么,以及它们是否是异步的

public async Task<byte[]> GetAsync(string key)
{
    async Task<byte[]> Action() => await this.Cache.GetAsync(key);
    return await this.Execute(Action);
}
现在,当我们看方法时,它在:

public async Task<byte[]> GetAsync(string key)
{
    return await this.Execute(Action);
}
这里我们调用了一个异步方法,但是我们没有返回它给我们的
任务。这意味着我们无法知道操作何时完成,或者是否成功。由于
deleteAscync
是异步的(或者我们可以假设,给定名称),我们知道该方法将在启动异步操作后立即返回,而不是在底层操作完成后返回

public async Task DeleteAsync(string key)
{
    await this.Execute(Action);
}
这不能编译
Action
这里有一个返回
void
的方法,因此您正在调用返回
void
Execute
重载,并且您不能
等待
一个
void
表达式。如果将代码更改为:

public async Task DeleteAsync(string key)
{
    Task Action() => this.Cache.DeleteAsync(key);
    await this.Execute(Action);
}
然后它将编译,因为您将调用接受
Func
并返回结果的
Execute
版本,因此您可以等待该任务,但是,正如我们从前面的方法中看到的,等待它除了增加一些开销之外没有任何用处,我们可以返回任务并完成它

private void Execute(Action action)
{
    this.Execute(() =>
    {
        action();
        return 0;
    });
}
如果我们进行上面指出的更改,就永远不会调用它,因为我们永远不会传入返回
void
的委托

private T Execute<T>(Func<T> action)
{
    if (someCondition)
    {
        try
        {
            return action();
        }
        catch (RedisConnectionException)
        {
            //do something
        }
    }
    else
    {
        // do something else
    }

    return default(T);
}
然后是在任务中没有结果的方法的重载:

private Task ExecuteAsync(Func<Task> action)
{
    return this.ExecuteAsync(async () =>
    {
        await action();
        return 0;
    });
}
private Task ExecuteAsync(Func操作)
{
返回这个.ExecuteAsync(异步()=>
{
等待行动();
返回0;
});
}

因此,首先要介绍的是,异步的方法并不意味着“它上面有
async
关键字”。当方法非常快地返回到调用方,然后在返回到调用方并允许调用方继续做它想做的事情之后,完成对它的任何操作时,它就是异步的。通常,这还涉及调用方以某种方式知道操作何时完成,是否成功,有时还包括操作的某些结果

async
关键字所做的只是允许该方法包含
wait
关键字。如果您没有将方法标记为a
async
,它就不知道
await
的任何用法实际上是否只有常规变量名,而不是一个特殊的关键字。
await
所做的是,您希望该方法在等待的任务完成后,安排在
await
之后运行的任何代码

记住这一点,我们可以检查您的方法,看看它们在做什么,以及它们是否是异步的

public async Task<byte[]> GetAsync(string key)
{
    async Task<byte[]> Action() => await this.Cache.GetAsync(key);
    return await this.Execute(Action);
}
现在,当我们看方法时,它在:

public async Task<byte[]> GetAsync(string key)
{
    return await this.Execute(Action);
}
这里我们调用了一个异步方法,但是我们没有返回它给我们的
任务。这意味着我们无法知道操作何时完成,或者是否成功。由于
deleteAscync
是异步的(或者我们可以假设,给定名称),我们知道该方法将在启动异步操作后立即返回,而不是在底层操作完成后返回

public async Task DeleteAsync(string key)
{
    await this.Execute(Action);
}
这不能编译
Action
这里有一个返回
void
的方法,因此您正在调用返回
void
Execute
重载,并且您不能
等待
一个
void
表达式。如果将代码更改为:

public async Task DeleteAsync(string key)
{
    Task Action() => this.Cache.DeleteAsync(key);
    await this.Execute(Action);
}
然后它将编译,因为您将调用接受
Func
并返回结果的
Execute
版本,因此您可以等待该任务,但是,正如我们从前面的方法中看到的,等待它除了增加一些开销之外没有任何用处,我们可以返回任务并完成它

private void Execute(Action action)
{
    this.Execute(() =>
    {
        action();
        return 0;
    });
}
如果我们进行上面指出的更改,就永远不会调用它,因为我们永远不会传入返回
void
的委托

private T Execute<T>(Func<T> action)
{
    if (someCondition)
    {
        try
        {
            return action();
        }
        catch (RedisConnectionException)
        {
            //do something
        }
    }
    else
    {
        // do something else
    }

    return default(T);
}
然后是在任务中没有结果的方法的重载:

private Task ExecuteAsync(Func<Task> action)
{
    return this.ExecuteAsync(async () =>
    {
        await action();
        return 0;
    });
}
private Task ExecuteAsync(Func操作)
{
返回这个.ExecuteAsync(异步()=>
{
等待行动();
返回0;
});
}

我不明白你所说的“异步运行”是什么意思。当发生以下两种情况时,代码是异步的:(1)表示高延迟工作的方法快速返回给调用方,(2)高延迟工作流的继续被安排在完成后执行。这些事情在你的程序中发生了吗?你到底在问什么?线程是否不会被阻塞,以便在等待缓存响应时执行其他操作