0

我在Windows Phone 8應用程序中有本地數據庫。該應用程序包括對數據庫的很多查詢,我不希望對UI的響應性產生不良影響。在數據庫查詢中使用關鍵字async/await

例如我有一個用戶和方法的表,用於通過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); 
} 

異步/等待

但我想用關鍵字異步/等待數據庫。

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

請不要[cross-post](http://codereview.stackexchange.com/q/40068/2041)將您的問題提交給多個SE網站。 – svick

+0

對不起,我想很快得到答案。在未來,這不會再發生:) – Alexandr

回答

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)。

+1

斯蒂芬克萊裏非常感謝你的答案! – Alexandr

相關問題