Azure编程笔记(5):长时间的异步操作带来的问题
来源:互联网 发布:盛世下的蝼蚁 知乎 编辑:程序博客网 时间:2024/06/07 19:44
内容提要
Azure Storage里很多操作需要花费很长的时间。为了提高效率,这些耗时的操作是以异步的方式响应的。也就是说调用这些操作对应的函数虽然结束,但背后的操作可能还要持续一段时间。如果没有合理的对待从函数返回到操作真正结束这段时间,我们的程序就有可能出现问题。下面以删除CloudTable为例讨论这类问题。
问题描述
我们写一个简单的单元测试的Class来重现这个问题。首先我们定义两个函数,分别用来初始化测试函数和清理测试函数所留下的数据。函数InitializeTest初始化一个名叫TestTable的CloudTable。如果该表不存在,则创建它。函数CleanupTest删除该表格。
private const string tableName = "TestTable";private CloudTable table;CloudTableClient tableClient;[TestInitialize]public void InitializeTest(){ string connectionString = Constant.connectionString; CloudStorageAccount storageAccount = Utilities.GetStorageAccount(connectionString); tableClient = storageAccount.CreateCloudTableClient(); this.table = tableClient.GetTableReference(tableName); this.table.CreateIfNotExists();}[TestCleanup]public void CleanupTest(){ if(table != null) { table.DeleteIfExists(); }}
为了使简化我们将要讨论的问题,我们添加两个看起来会永远通过的测试用例:
[TestMethod]public void TestMethod1(){ Assert.IsTrue(true);}[TestMethod]public void TestMethod2(){ Assert.IsTrue(true);}
当我们在Visual Studio中运行上述两个测试用例时,却发现只有一个测试用例能够通过测试,另外一个测试用例则会抛出如下的异常:
问题根源
运行上述测试用例,第一个测试用例顺利完成,但在初始化第二个测试用例调用CreateIfNotExist试图创建CloudTable的时候出错了。从上面的异常信息的截图中我们可以看出,该异常的错误代码是TableBingDeleted。
这个错误代码告诉我们的信息是,在清理第一个测试用例的数据时,调用DeleteIfExists删除CloudTable虽然顺利返回,但实际上删除操作并没有立即结束,只是在后台简单地设一个标签说该CloudTable需要被删除就返回了而已。真正删除一个CloudTable可能需要40秒甚至更多的时间。如果我们在DeleteIfExists结束之后立即调用CreateIfNotExist重新创建同一个CloudTable的时候,该表格实际上还存在并处在正被删除的状态,因此再次创建的操作无法完成。
解决问题
在本文的例子中,我们删除CloudTable仅仅是因为需要清理前一个测试遗留的数据。我们删除数据可以不删除整个CloudTable,而清除CloudTable里的所有数据。删除CloudTable里的数据(通过TableOperation.Delete)是同步的,如果函数返回,Azure会保证数据一定被删除。
如果我们一定要删除整个CloudTable,那么在创建CloudTable的时候就得做好错误处理。下面是一段调用CloudTable.CreateIfNotExists的参考代码:
[TestInitialize]public void InitializeTest(){ string connectionString = Constant.connectionString; CloudStorageAccount storageAccount = Utilities.GetStorageAccount(connectionString); tableClient = storageAccount.CreateCloudTableClient(); table = tableClient.GetTableReference(tableName); int retryTimes = 0; int maxRetryTimes = 20; StorageException lastException = null; while (retryTimes < maxRetryTimes) { try { table.CreateIfNotExists(); break; } catch (StorageException excep) { var extendedInformation = excep.RequestInformation.ExtendedErrorInformation; var errorCode = extendedInformation.ErrorCode; if (errorCode == "TableBeingDeleted") { retryTimes++; lastException = excep; Thread.Sleep(5 * 1000); // Sleep 5 seconds } else { throw; } } } if(retryTimes == maxRetryTimes && lastException != null) { throw lastException; }}
- Azure编程笔记(5):长时间的异步操作带来的问题
- Azure编程笔记(2):重复CloudTable的修改操作
- 嵌入式软件异步编程:异步带来的性能提升
- Azure编程笔记(4):配置Cloud Service的证书
- Azure编程笔记(3):用Fiddler调试Azure的应用程序
- freemarker数字格式化带来的操作问题
- SharePoint的长时间操作SPLongOperation
- WCF:异步调用长时间工作的服务
- WCF异步调用中客户端关闭带来的性能问题
- Jquery ajax异步请求带来的问题及解决方案
- SQL事务以及带来的问题 笔记
- Windows Azure 系列-- Azure Queue的操作
- 异步操作的简单笔记
- Pro Android学习笔记(九九):BroadcastReceiver(3):长时间运行Receiver的问题
- (Kevin笔记三)用AtomicInteger来解决数据表异步操作的问题
- 异步方法中map、forEach和for循环中带来的异步执行问题
- 【数据库】数据库并发操作(一)数据库并发操作带来的问题
- 感受DataGrid给数据操作带来的便利(5)
- 【Unity3D】【NGUI】如何动态给EventDelegate添加参数
- C# - CSV file reader
- OCP exam notes
- 数据挖掘笔记-分类-支持向量机SVM-1
- webApp前端开发技巧总结
- Azure编程笔记(5):长时间的异步操作带来的问题
- jQuery操作input改变value属性值
- ROR incompatible character encodings: UTF-8 and ASCII-8BIT 错误的 解决办法
- Find 7轻装版和正式版
- urlEncode&&urldecode的用法
- ThinkPHP的ACTION_NAME
- AndroidActivity跳转动画,让你的APP瞬间绚丽起来
- Jlink 采用 SWD 模式下载电路接法
- 关于struct的初始化的说明