Blu*_*Sky 1 c# asp.net asynchronous async-await .net-4.5
如何异步执行以下两种方法(StoreInSql,StoreInOtherDatabase),然后在设置标签输出消息之前等待两个结果都返回?可以使用await关键字干净地完成吗?非常感谢你.
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 = "test@test.com";
// 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
最好的方法是使用异步数据库访问(例如,EF6):
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用Task.WhenAll和自然地消耗它们await:
protected async void Page_Load(object sender, EventArgs e)
{
string email = "test@test.com";
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!";
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我使用的async void是简单,但ASP.NET团队更喜欢PageAsyncTask 按照教程中的描述使用.