Reputation: 1901
I have a local database in Windows Phone 8
app. The app includes a lot of queries to the database and I don't want bad effect on the responsiveness of UI.
For example I have a table of users and method to get a user from database by id.
Current variant
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();
}
}
}
I need ensure safety of the data if at the same time on database allow different requests to add, update, delete data. For this I use AutoResetEvent
. Not sure what I'm doing it right, but so far no problems.
I can get user from the database:
using (DataBaseUser = new CacheDataContextFriends(ConnectionString))
{
var user = DataBaseUser.GetUser(id);
}
Async/await
But I want work with the database using keywords 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;
}
}
}
I'm afraid to rewrite the method as described above, because I'm not sure it's right. Please tell me what the problem may be. My main goal is to improve the responsiveness of the app.
Upvotes: 0
Views: 2637
Reputation: 456917
First, AutoResetEvent
is the wrong thing to use for exclusive access. In Windows, an "event" like this is a message from one thread to another; in this case, you just want a simple lock:
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
}
}
}
}
If you want to improve your responsiveness, then call your data context methods using Task.Run
, i.e.:
var user = await Task.Run(() => GetUser(id));
Do not expose asynchronous methods on your data context unless the actual database access is asynchronous (i.e., using EF6, not Task.Run
).
Upvotes: 6