Ste*_*han 1 c# async-await litedb
从以下(简化)接口开始,考虑到async/await,我想通过使用LiteDB数据库来实现它.
public interface IDataService
{
Task<User> GetUserAsync(int key);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,LiteDB目前不支持异步方法.所有方法都是同步的.
我尝试了以下内容,但后来遇到了一些问题(进程并没有真正等待任何原因).接下来,我读到你应该只Task.Run()用于CPU绑定算法,因此不能用于数据库访问.
public Task<User> GetUserAsync(int key)
{
var task = Task.Run(() =>
{
return _users
.Find(x => x.Key == key)
.SingleOrDefault();
});
return task;
}
Run Code Online (Sandbox Code Playgroud)
即使我阅读了几篇博客文章和SO问题,我仍然不清楚如何为基于同步IO的代码制作一个正确编写的等待方法.
那么我该如何编写一个正确的等待方法呢?
注意:我无法更改界面.这是给出的.
你不能使用Task.Run.这不是道德上正确的事情.如您所知,将工作线程分配给不受CPU限制的任务在道德上是错误的,但这不是问题.这里的问题是LiteDB是单线程的,并且在尝试将调用移入工作线程时不会构建为健壮.
更新:显然LiteDB在版本4中是线程安全的,根据一位评论者可能比我在这个问题上更有信息.因此,请参阅LiteDB文档,了解它是什么类型的线程安全.并非所有线程安全对象都可以在没有任何限制的情况下使用.
你的选择是:
FromResult是正确的方法.LiteDB,包括创建和销毁与此数据库关联的每个对象.(可能在进程中,但是,如果你愿意的话,你可以把它放在自己的进程中.)为LiteDB实现你自己的异步前端,它适当地调用来自这个专用线程的调用.是的,您刻录了大部分时间都在睡觉的整个线程,但这是您使用同步数据库所付出的代价.满足所有规定约束的解决方案是最后一个.它也是最适合你的那个.正如木工喜欢说的那样:你将节省在廉价材料上的费用.尝试将正确的异步接口改进到非异步但I/O绑定的单线程库是一个棘手的问题.祝好运!