我理解Silverlight的Async特性,但是一直阻碍我编写有效UI的能力的一件事是竞争条件和使用加载带外数据的对象引起的重入问题。有没有办法强制在代码中强制执行带外操作?
例如,假设我有一个带有Load方法的对象,其唯一的工作是将数据从流加载到Textbox中。如果我称之为Async:
Object.Load( targetbox1 );
Object.Load( targetbox2 );
Object.Load( targetbox3 );
目标框将按任何给定顺序加载。如果我因任何原因重新输入加载代码,则会尝试同时进行两次加载并推入导致异常的同一文本框。大多数这些对象支持事件,我可以连接回调:
Object.Loaded ( s, e ) => {
Object.Load( targetbox2 );
Object.Loaded( s, e ) => {
...
}
}
Object.Load( targetbox1 );
但你看到了嵌套的问题。
是否有任何简单的方法让这些操作以串行方式运行,以便一个调用在前一个调用完成之前不会进行,但是以一种简单直观的方式进行,可以全面应用?
答案 0 :(得分:3)
我写了几篇博客文章here和here来解决这个问题。第一部分详细描述了解决方案的内部,第二部分介绍了如何使用场景。
以下是您的对象Load / Loaded的伪示例: -
AsyncOperation Load(YourObject subject, TextBox target)
{
return (completed) =>
{
EventHandler eh = null;
eh = (s, args) =>
{
subject.Loaded -= eh;
completed();
}
subject.Loaded += eh;
subject.Load(target);
}
}
你的序列看起来像这样: -
IEnumerable<AsyncOperation> LoadTextBoxes()
{
yield return Load(subject1, textbox1);
yield return Load(subject2, textbox2);
yield return Load(subject3, textbox3);
}
并执行: -
LoadTextBoxes().Run(e =>
{
if (e != null)
{
//Something bad happened.
}
});
主要目标是保证序列,只要你喜欢没有讨厌的嵌套,就可以使用循环,你甚至可以包含其他代码来执行序列中的特定点。