我有一个BindingList<>绑定到DataGridView的对象。这些对象包含另一个对象的外键,第一个对象的某些列用于显示外键对象的只读字段。
我以为我可以将外部对象的副本保存为私有变量,如果这是null,我会向webservice发出获取请求以获取外部对象,然后在相关字段上调用NotifyPropertyChanged()指示已加载外部对象并更新DataGridView中的这些字段。
这很有效 - 至关重要。对于大量记录,似乎某些任务运行并且永远不会返回,即使取消也是如此。有没有更好的方法呢?
private ForeignObj _foreignObject = null;
public string ForeignName
{
get
{
if (!_foreignKey.HasValue)
return null;
if (_foreignObject == null)
{
GetForeignObject(); // method is async, so it spawns a task and returns immediately
return "Fetching...";
}
return _foreignObject.Name;
}
}
CancellationTokenSource foreignObjectToken = null;
public async Task GetForeignObject()
{
if (foreignObjectToken != null)
return; // Don't call it again while it is already fetching
foreignObjectToken = new CancellationTokenSource();
foreignObjectToken.CancelAfter(10000); // Don't let request go longer than 10 seconds
_foreignObject = await DTOPropertyHelper.GetForeignObject(_foreignKey.Value, foreignObjectToken.Token); // HTTP request to web service to obtain foreign object
OnPropertyChanged("ForeignName");
foreignObjectToken = null;
}
更新:我发现这个'有效'在属性getter中,但是很难看:
get
{
if (!_foreignKey.HasValue)
return null;
if (_foreignObject == null)
{
if (DTOPropertyHelper.NumTasks < DTOPropertyHelper.MaxTasks)
GetForeignObject();
else
OnPropertyChanged("ForeignName");
return null;
}
return _foreignObject.Name;
}
...基本上不断触发PropertyChanged事件,该事件继续锤击任务创建,提供少于MaxTasks的数字是有效的(DTOPropertyHelper.GetForeignObject()自动递增和递减NumTasks)。
答案 0 :(得分:0)
我假设您有更多属性,例如ForeignName
,显示_foreignObject
的字段?然后,您在创建foreignObjectToken
和检查null
之间有一个竞争条件,因为您的async
方法已经是Task
(意味着它)在自己的线程中运行)。如果是这种情况,您应该使用foreignObjectToken
保护lock
:
Object foreignObjectTokenLock = new Object();
CancellationTokenSource foreignObjectToken = null;
public async Task GetForeignObject()
{
lock (foreignObjectTokenLock)
{
if (foreignObjectToken != null)
return; // Don't call it again while it is already fetching
foreignObjectToken = new CancellationTokenSource();
}
foreignObjectToken.CancelAfter(10000); // Don't let request go longer than 10 seconds
_foreignObject = await DTOPropertyHelper.GetForeignObject(_foreignKey.Value, foreignObjectToken.Token); // HTTP request to web service to obtain foreign object
OnPropertyChanged("ForeignName");
// I guess there should be some more OnPropertyChanged()?
foreignObjectToken = null;
}
我必须补充一点,我不清楚这种竞争条件会导致任务根本没有返回(除了Web服务调用可能会以某种方式永久地挂起),所以也许这还不是整个解决方案。