在数据库查询中使用关键字async/await

Ale*_*ndr 0 c# thread-safety windows-phone-7 async-await windows-phone-8

我在Windows Phone 8应用程序中有一个本地数据库.该应用程序包含对数据库的大量查询,我不希望对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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果数据库同时允许不同的请求添加,更新,删除数据,我需要确保数据的安全性.为此,我使用AutoResetEvent.不确定我做得对,但到目前为止没有问题.

我可以从数据库中获取用户:

using (DataBaseUser = new CacheDataContextFriends(ConnectionString))
{
   var user = DataBaseUser.GetUser(id);
}
Run Code Online (Sandbox Code Playgroud)

异步/ 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;          
        }       
    }
}
Run Code Online (Sandbox Code Playgroud)

我害怕重写上面描述的方法,因为我不确定它是对的.请告诉我可能是什么问题.我的主要目标是提高应用程序的响应能力.

Ste*_*ary 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 
        }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果要提高响应速度,请使用Task.Run,即调用数据上下文方法:

var user = await Task.Run(() => GetUser(id));
Run Code Online (Sandbox Code Playgroud)

不要使你的数据上下文异步方法,除非实际的数据库访问是异步的(即使用EF6,没有 Task.Run).