我有一些基本的Azure表格,我一直在串行查询:
var query = new TableQuery<DynamicTableEntity>()
.Where(TableQuery.GenerateFilterCondition("PartitionKey",
QueryComparisons.Equal, myPartitionKey));
foreach (DynamicTableEntity entity in myTable.ExecuteQuery(query)) {
// Process entity here.
}
为了加快速度,我这样并行化处理:
Parallel.ForEach(myTable.ExecuteQuery(query), (entity, loopState) => {
// Process entity here in a thread-safe manner.
// Edited to add: Details of the loop body below:
// This is the essence of the fixed loop body:
lock (myLock) {
DataRow myRow = myDataTable.NewRow();
// [Add entity data to myRow.]
myDataTable.Rows.Add(myRow);
}
// Old code (apparently not thread-safe, though NewRow() is supposed to create
// a DataRow based on the table's schema without changing the table state):
/*
DataRow myRow = myDataTable.NewRow();
lock (myLock) {
// [Add entity data to myRow.]
myDataTable.Rows.Add(myRow);
}
*/
});
这会显著提高速度,但运行结果在某些方面略有不同(即,有时实体会偶尔不同,尽管返回的实体数量完全相同)。
通过这一点和一些网络搜索,我得出结论:上述枚举器并不总是线程安全的。文档似乎表明只有当表对象为公共静态时才保证线程安全,但这对我没有任何影响。
请问有人能建议如何解决这个问题吗?是否有标准的 Azure 表查询并行模式?
Parallel.ForEach()
可以处理。问题可能出现在实体共享某些状态的情况下。 - svickDataTable.NewRow()
调用移到了我的关键部分里面。我不明白为什么这是必要的,因为这个调用只是根据表的模式创建一个新行,而不影响任何表状态(.NET DataTable,而不是 Azure 表)。因此,我不确定问题是否真正解决了,但是到目前为止代码一直都能工作。 - Paul Lambert