2014-01-27 26 views
1

如何異步執行以下兩種方法(StoreInSql,StoreInOtherDatabase),然後在設置標籤輸出消息之前等待兩個結果返回?這可以用await關鍵字乾淨地完成嗎?非常感謝你。如何異步執行ASP.NET 4.5 WebForms中的兩個I/O綁定任務?

using Microsoft.WindowsAzure.Storage; 
using Microsoft.WindowsAzure.Storage.RetryPolicies; 
using Microsoft.WindowsAzure.Storage.Table; 
using System; 
using System.Web.UI; 

namespace UpdateStorage 
{ 
    public partial class _Default : Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      string email = "[email protected]"; 

      // It takes approximately 300 ms to store in SQL Azure 
      bool sqlStorageSuccessful = MyAppStorage.StoreInSqlAzureViaEF(email); 

      // It takes approximately 300 ms to store in Azure Table Storage 
      bool otherdbStorageSuccessful = MyAppStorage.StoreInAzureTableStorage(email); 

      if (sqlStorageSuccessful && otherdbStorageSuccessful) 
      { 
       labelOutputMessage.Text = "Successfully stored the email."; 
      } 
      else 
      { 
       labelOutputMessage.Text = "We couldn't store the email, sorry!"; 
      } 

      // 300ms + 300ms = It takes 600ms for this Page_Load method to complete. 
      // How can I write it using the "await" keyword so that it only takes ~ 300ms? 
     } 
    } 
    public static class MyAppStorage 
    { 
     public static bool StoreInSqlAzureViaEF(string s) 
     { 
      try 
      { 
       using (MyDataModelContainer db = new MyDataModelContainer()) 
       { 
        Email e = new Email(); 
        e.EmailAddress = s; 
        db.SaveChanges(); 
       } 
      } 
      catch (Exception) 
      { 
       return false; 
      } 
      return true; 
     } 
     public static bool StoreInAzureTableStorage(string s) 
     { 
      try 
      { 
       AzureEmailMessage a = new AzureEmailMessage(); 
       a.EmailAddress = s; 
       a.Save(); 
      } 
      catch (Exception) 
      { 
       return false; 
      } 
      return true; 
     } 
    } 
    public static class AzureStorage 
    { 
     private static string _ConnectionString = "DefaultEndpointsProtocol=http;AccountName=myaccount;AccountKey=mykey"; 

     static AzureStorage() { } 

     private static CloudTable GetTableRef(string tableName) 
     { 
      CloudStorageAccount account = CloudStorageAccount.Parse(_ConnectionString); 
      CloudTableClient tableClient = account.CreateCloudTableClient(); 
      IRetryPolicy linearRetryPolicy = new LinearRetry(TimeSpan.FromSeconds(2), 10); 
      tableClient.RetryPolicy = linearRetryPolicy; 
      CloudTable table = tableClient.GetTableReference(tableName); 
      table.CreateIfNotExists(); 
      return table; 
     } 
     public static bool SaveObject(ITableEntity entity) 
     { 
      try 
      { 
       string tableName = entity.GetType().ToString(); 
       int lastNs = tableName.LastIndexOf("."); 
       if (lastNs > 0) 
       { 
        tableName = tableName.Substring(lastNs + 1); 
       } 
       CloudTable table = GetTableRef(tableName); 
       TableOperation insertOperation = TableOperation.Insert(entity); 
       table.Execute(insertOperation); 
       return true; 
      } 
      catch (Exception) 
      { 
       return false; 
      } 
     } 
    } 
    public class AzureEmailMessage : TableEntity 
    { 
     public string EmailAddress { get; set; } 

     public AzureEmailMessage() { } 

     public bool Save() 
     { 
      return AzureStorage.SaveObject(this); 
     } 
    } 
} 
+1

你是什麼意思的「最好?」 –

+0

編輯問題以澄清問題的重點在於異步執行,然後等待。感謝您的入門。 – BlueSky

+2

'MyAppStorage'公開了像IAsyncResult BeginStoreInSql('或'Task StoreInSqlAsync('或者是否可以修改類以正確創建它們的方法)的異步方法嗎? –

回答

6

最好的辦法是使用異步數據庫訪問(例如,EF6):

protected async void Page_Load(object sender, EventArgs e) 
{ 
    string email = "[email protected]"; 

    bool[] success = await Task.WhenAll(MyAppStorage.StoreInSqlAsync(email), 
     MyAppStorage.StoreInOtherDatabaseAsync(email)); 
    if (success[0] && success[1]) 
    { 
     labelOutputMessage.Text = "Successfully stored the email."; 
    } 
    else 
    { 
     labelOutputMessage.Text = "We couldn't store the email, sorry!"; 
    } 
} 

在這個例子中:

public static class MyAppStorage 
{ 
    public static Task<bool> StoreInSqlAsync(string s) 
    { 
     return FakeStorageJobAsync(s); 
    } 
    public static Task<bool> StoreInOtherDatabaseAsync(string s) 
    { 
     return FakeStorageJobAsync(s); 
    } 

    private static async Task<bool> FakeStorageJobAsync(string s) 
    { 
     // This simulates waiting on a SQL database, or a web service, or any other storage task. 
     await Task.Delay(300); 
     return true; 
    } 
} 

然後你就可以自然地使用Task.WhenAllawait使用它們,爲簡單起見,我使用async void,但ASP.NET團隊更喜歡使用PageAsyncTaskas described in the tutorial

+0

Stephen,非常感謝你的答覆。我已經編輯了這個問題,包括一個通過SQL Azure EF保存對象的例子,還有在這種情況下你會如何編寫它?再次感謝! – BlueSky

+1

像[this](http://msdn.microsoft.com/en-us/data/jj819165.aspx)用於EF6,並使用' * Azure表存儲的Async'方法。 –