我在Windows Phone 8
app中有一个本地数据库。该应用程序包含对数据库的大量查询,我不希望对UI的响应性产生不良影响。
例如,我有一个用户表和方法,用于通过id从数据库中获取用户。
当前变体
public class CacheDataContext : DataContext
{
public static string DBConnectionString = "Data Source=isostore:/Cache.sdf";
public CacheDataContext(string connectionString)
: base(connectionString) { }
public static AutoResetEvent OperationOnDatabaseUser = new AutoResetEvent(true);
public Table<User> UserItems;
}
public class CacheDataContextUser : CacheDataContext
{
public CacheDataContextUser(string connectionString)
: base(connectionString) { }
public User GetUser(string id)
{
try
{
OperationOnDatabaseUser.WaitOne();
using (CacheDataContext context = new CacheDataContext(DBConnectionString))
{
//find user in the data base and return
}
}
finally
{
OperationOnDatabaseUser.Set();
}
}
}
如果数据库同时允许不同的请求添加,更新,删除数据,我需要确保数据的安全性。为此我使用AutoResetEvent
。不确定我做得对,但到目前为止没有问题。
我可以从数据库中获取用户:
using (DataBaseUser = new CacheDataContextFriends(ConnectionString))
{
var user = DataBaseUser.GetUser(id);
}
异步/ AWAIT
但我希望使用关键字async / await来处理数据库。
public class CacheDataContextUser : CacheDataContext
{
public CacheDataContextUser(string connectionString)
: base(connectionString) { }
private object threadLock = new object();
public Task<User> GetUser(string id)
{
using (CacheDataContext context = new CacheDataContext(DBConnectionString))
{
var result = await Task<User>.Factory.StartNew(() =>
{
lock (threadLock)
{
//find user in the data base and return
}
});
return result;
}
}
}
我害怕改写上面描述的方法,因为我不确定它是对的。请告诉我可能是什么问题。我的主要目标是提高应用程序的响应能力。
答案 0 :(得分:6)
首先,AutoResetEvent
用于独占访问是错误的。在Windows中,像这样的“事件”是从一个线程到另一个线程的消息;在这种情况下,你只需要一个简单的锁:
public class CacheDataContext : DataContext
{
public static string DBConnectionString = "Data Source=isostore:/Cache.sdf";
public CacheDataContext(string connectionString)
: base(connectionString) { }
protected static readonly object OperationOnDatabaseUser = new object();
public Table<User> UserItems;
}
public class CacheDataContextUser : CacheDataContext
{
public CacheDataContextUser(string connectionString)
: base(connectionString) { }
public User GetUser(string id)
{
lock (OperationOnDatabaseUser)
{
using (CacheDataContext context = new CacheDataContext(DBConnectionString))
{
//find user in the data base and return
}
}
}
}
如果您想提高响应能力,请使用Task.Run
调用您的数据上下文方法,即:
var user = await Task.Run(() => GetUser(id));
除非实际的数据库访问是异步的(即使用EF6,不是 Task.Run
),否则不要在数据上下文中公开异步方法。