如何最好地将异步任务返回给调用者



我将在Cassandra中插入行,尽管我的问题是关于Cassandra,但一般来说如何最好地使用异步API。简而言之,我在C#代码中为一行生成一个id,并异步插入,并希望将id返回给调用者。下面的示例代码显示了我迄今为止所尝试的内容,所有这些都有效,但哪一个最好?是否有替代方案或更好的解决方案?

比如说,我有一些课,所有的卡桑德拉gubbins设置。这同样可以是我正在将类序列化到的一个文件;这不是卡桑德拉的问题。

class MyClass
{
    public Guid Id { get; set; }
    public string Text { get; set; }
}
ISession cassandraSession;
PreparedStatement preparedStatement;

我的第一次尝试是使用async+await

async Task<Guid> Insert(MyClass someObject)
{
    someObject.Id = TimeUuid.NewId();
    BoundStatement insert = preparedStatement.Bind(someObject.Id, someObject.Text);
    await cassandraSession.ExecuteAsync(insert);
    return someObject.Id;
}

经过一些研究,我认为这是次优的,因为它会阻塞await并创建一个全新的状态机等

接下来我尝试了这个:

Task<Guid> Insert(MyClass someObject)
{
    someObject.Id = TimeUuid.NewId();
    BoundStatement insert = preparedStatement.Bind(someObject.Id, someObject.Text);
    cassandraSession.ExecuteAsync(insert);
    return Task.FromResult(someObject.Id);
}

看起来还可以,没有阻塞,但调用方是否可以在插入完成之前收到id和查询,却找不到行?我尝试了一个延续:

Task<Guid> Insert(MyClass someObject)
{
    someObject.Id = TimeUuid.NewId();
    BoundStatement insert = preparedStatement.Bind(someObject.Id, someObject.Text);
    return cassandraSession
        .ExecuteAsync(insert)
        .ContinueWith(t => someObject.Id);
}

这似乎也有效,这意味着调用者等待的任务将包括插入,因此应该确保插入已经完成。

我有没有遗漏或误解什么?

await没有阻塞,因此您的语句在技术上是不准确的。但我相信你的意思是"它不会继续执行",这是正确的。

创建一个全新的状态机

是的,但是很便宜。如果我计算正确的话,这里的await+async负责4个小对象的分配。这并没有那么重要。特别地,由于高昂的数据库调用,它在噪声中消失了。

您的尝试2不可能如您所认识到的那样成功。

尝试3有效,但代码质量较差。首选1。

最新更新