我们有一个具有主窗口的应用程序,它可以在新的浏览器中启动多个其他窗口。我们在主窗口中使用silverlight应用程序作为协调服务器来关闭所有属于应用程序的窗口,无论它们是如何打开的(我们不能保证它是通过window.open所以不要总是有javascript中窗口的句柄。)
注销时,我们希望发出所有其他窗口的信号,以便在必要时执行自动保存,然后关闭。
因此所有窗口都有一个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);
}
由于从无法取消的javascript onunload事件调用ProcessAutosave,我们需要在从每个子窗口处理响应之前使其同步并且不完整,因此会话状态仍然有效等。
在SenderSendCompleted中,当他们说已经完成时,我们会从_windows中删除项目。
所以我在最后加了一个循环:
while(_windows.Count > 0) {
Thread.Sleep(1)
}
但是,除非我在其上放置迭代计数器,否则永远不会终止。
我是否是编译器优化的受害者,这意味着SenderSendCompleted中的更改不会影响while循环,或者,我是否从根本上误解了某些内容?或者错过了一些明显盯着我的东西?
答案 0 :(得分:0)
由于同步/异步,这听起来像种族情况的微妙版本。 queston 中的进程是否还无法接收来自已收到消息并正在关闭的窗口的通知?收到所有计数器消息后,主应用程序可能会在没有忙碌等待的情况下关闭(?)。
答案 1 :(得分:0)
我找到了一种解决问题的方法。但是,这并不能真正“解决”这个问题,只是在我的情况下,这也只是支持Internet Explorer。
function WindowCloseEventHandler()
{
var app = // get silverlight app handle...
app.doAutoSave();
var params = 'whatever you need';
var args = new Object();
args.hwnd = window;
window.showModalDialog('blocker.aspx',args,params);
}
function checkAutoSave()
{
var app = // get silverlight app handle...
return app.autosavecomplete();
}
然后在blocker.aspx中我们显示一个静态的“执行注销处理程序”类型的消息并执行:
function timerTick()
{
if(window.dialogArguments.hwnd.checkAutoSave()) {
window.close();
} else {
setTimeout(timerTick, 500);
}
}
在窗口加载时启动计时器。
通知子窗口的silverlight应用程序启动自动保存,然后在完成后通知父级。然后,我们从模态对话框中轮询父级的状态,该对话框阻止WindowCloseEventHandler()的终止,我们已将其连接到正文的onclose事件。
这很糟糕而且非常可怕,但这意味着silverlight保持异步,我们正在使用javascript计时器,因此javascript没有加载系统。
当然,如果用户关闭模态对话,则可能存在问题。