2012-03-28 52 views
0

我们有一个具有主窗口的应用程序,它可以在新浏览器中启动多个其他窗口。我们使用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循环,或者我是否从根本上误解了某些内容?或者错过了一些显而易见的东西在我面前凝视着我?

回答

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应用程序启动自动保存,然后在完成后通知父项。然后我们从模态对话框中查询父对象的状态,该对话框阻止我们连接到正文的onclose事件的WindowCloseEventHandler()的终止。

这是hacky和可怕的,但它意味着silverlight保持异步,我们正在使用JavaScript计时器,所以JavaScript不加载系统。

当然,如果用户关闭模态对话,则存在潜在的问题。

0

这听起来像是由于进行同步/异步而导致的比赛情况的微妙变化。在queston 的过程中是否还有接收到来自窗口的通知,他们已收到该消息并正在关闭?一旦接收到所有的计数器消息,那么主应用程序可以关闭而不需要在最后(?)等待。

+0

问题在于onclose处理程序需要同步响应。只要我允许它异步并等待所有参与方做出响应,主事件处理程序就会完成处理,并关闭窗口以创建竞争条件。 – THEMike 2012-04-03 12:14:54