理解 await async 和 NHibernate

6

给出以下代码:

private ISession _session;

public async Task<T> GetAsync<T>(int id) where T : ISomeEntity
{
    //how to call and return _session.Get<T>(id) asynchronous
}

是否可能异步调用NHibernate ISession.Get<T>()?这样做是否可取?还是不值得?


2
NHibernate现在支持异步操作:http://enterprisecraftsmanship.com/2017/12/11/nhibernate-async-support/ - Vladimir
3个回答

14
NHibernate不支持Async Await,这与实体框架默认情况下不同。然而,如果可以的话,建议这样做,因为数据库调用是IO调用,非常适合进行异步处理。因此,当等待来自DB的响应时,您的线程将返回到池中,而不是挂起,这将使您的应用程序更具可扩展性。 现在谈到异步支持。我对NHibernate进行了分支以实现此功能。在我的分支中,我称之为NHibernateX,有像GetAsync、ListAsync和ToListAsync等异步方法。 以下是源代码和NuGet包链接:

https://github.com/ReverseBlade/nhibernate-core

https://www.nuget.org/packages/NHibernateX/


1
你好,我已经下载了NHibernateX库并仔细查看了它。我想知道你是否有任何示例可以分享,这样我就可以更好地了解如何使用它。谢谢! - MattB
1
@MattB,请查看此API更改,https://github.com/OnurGumus/nhibernate-core/commit/ef67c54724c24ce44915805331dd4af25917f15a - Onur Gumus
不管怎样,NHibernate现在支持async/await(自2017年起):https://enterprisecraftsmanship.com/posts/nhibernate-async-support/ - zcrar70

8
如果底层操作不是以某种异步方式进行的(例如async-await, BeginXXX/EndXXX等),那么在它周围添加一个async包装器是没有价值的。 async有两种用途:可扩展性和响应性。对于可扩展性,使用async over sync根本没有帮助;对于响应性,您可以简单地使用Task.Run将工作移交到另一个ThreadPool线程中,而无需添加专用方法。
更多信息请参见是否应该为同步方法公开异步包装器?

即使使用Async Await也会将执行卸载到线程池,这不是比使用Task更好的机制吗?因为Task从方法开始就会卸载。在这种情况下,它可以在不需要太多时间的情况下同步进行,并在使用await点后异步进行。 - Mrinal Kamboj
@MrinalKamboj async-await不会卸载到“线程池”。所有“async”关键字所做的就是让您在方法内部使用“await”,这里没有任何需要“await”的内容。 - i3arnon
在使用带有async标记的方法中使用await时,我们不是脱离了主线程/调用线程的上下文,因此必须使用单独的线程。实际上,异步方法的返回值大多是Task<T>。有趣的部分是,在await之后,它会切换回主/调用线程的上下文,例如UI。 - Mrinal Kamboj
在第一个 await 之前,执行在调用线程上。在 await 之后,通常会在 ThreadPool 线程或 UI 线程上。重要的是在其间发生的事情。当 (真正的) async 操作正在执行时,根本没有线程。但是这里没有要 await 的任务。您可以使用 Task.Run 创建一个任务,但这将在整个操作期间阻塞 ThreadPool 线程。 - i3arnon
异步比仅使用Task.Run更具响应性,因为它可以在以后显式地将代码调度回UI线程,而无需编写.NET 4.0样式的continuations。当然,在适当的时候,您也可以使用await等待Task.Run的结果。 - Jonathan Allen
@JonathanAllen 这里的 async 意味着一个异步包装器,没有必要添加。当然,如果你直接从 UI 代码中使用 Task.Run,并且这样做有意义,那么你可以等待它。 - i3arnon

6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接