我们有一个具有主窗口的应用程序,它可以在新浏览器中启动多个其他窗口。我们使用silverlight应用程序作为主窗口中的协调服务器,以关闭作为应用程序一部分的所有窗口,而不管它们是以何种方式打开的(我们无法保证它是通过window.open保证的,因此并不总是有在JavaScript中的窗口句柄)。同步使用LocalMessageSender
注销时,我们希望发信号通知所有其他窗口执行自动保存(如有必要),然后关闭。
所以所有的窗户都有一个silverlight应用程序,它们使用localmessagesenders进行协调。然而,这些都是异步的:
private void ProcessAutosave()
{
foreach (string s in _windows)
{
SendMessage(s, "notify-logout");
}
// code here quoted later...
}
// sendasynch doesn't send until the method terminates, so have to do it in it's own function.
private void SendMessage(string to, string message)
{
var lms = new LocalMessageSender(to);
lms.SendCompleted += new EventHandler<SendCompletedEventArgs>(SenderSendCompleted);
lms.SendAsync(message);
}
由于ProcessAutosave从无法取消一个javascript onunload事件中调用,我们需要这是同步的,不完整的,我们必须从每个子窗口处理的响应之前所以会话状态仍然有效等。
在SenderSendCompleted中,我们从_windows中删除项目,当他们说他们已经完成。
所以我说在结束一个循环:
while(_windows.Count > 0) {
Thread.Sleep(1)
}
然而,永远不会终止,除非我把一个迭代计数器就可以了。
我是编译器优化的受害者,这意味着SenderSendCompleted中的更改不会影响while循环,或者我是否从根本上误解了某些内容?或者错过了一些显而易见的东西在我面前凝视着我?
问题在于onclose处理程序需要同步响应。只要我允许它异步并等待所有参与方做出响应,主事件处理程序就会完成处理,并关闭窗口以创建竞争条件。 – THEMike 2012-04-03 12:14:54