2011-03-14 53 views
0

我知道所有浏览器都是单线程的,不可能在JavaScript或Flash Player Thread.sleep中实现。我决定尝试使用“System.Threading”库实现Silverlight中的Thread.Sleep。在Thread.Sleep的Internet Explorer中删除死锁?

App.xaml.cs

using System.Windows; 
using System.Windows.Browser; 
using System.Threading; 

namespace ThreadSleep 
{ 
    public partial class App : Application 
    { 

     public App() 
     { 
      InitializeComponent(); 
      HtmlPage.RegisterScriptableObject("App", this); 
     } 

     [ScriptableMember] 
     public void Sleep(int mlsec) 
     { 
      Thread.Sleep(mlsec); 
     } 
    } 
} 

所以,从JavaScript代码我可以执行休眠功能,但我的Internet Explorer的冻结和没有响应。

这是我的例子:

的Index.html

<HTML> 
<BODY> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
    var SleepInterval = 10000; 

    function pause1(){ 
     window.showModalDialog("PauseWin.html", this, 'dialogWidth:255px; dialogHeight:105px; status:0; scroll:0;'); 
     alert("Resume"); 
    } 
    function pause2(){ 
     var control = document.getElementById("SleepSL"); 
     control.Content.App.Sleep(SleepInterval); 
     alert("Resume"); 
    } 
    function tick(){ 
     var clock = document.getElementById("clock"); 
     if(clock) clock.innerHTML = new Date(); 
    } 
    setInterval(tick, 1000); 
//--> 
</SCRIPT> 
<INPUT TYPE="button" value="Pause Modal Dialog" onclick="pause1()"> 
<INPUT TYPE="button" value="Pause Thread Sleep" onclick="pause2()"> 
<BR><BR> 

<!--Youtube Video --> 
<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/RWNcGBSP0Wg?autoplay=1" frameborder="0" allowfullscreen></iframe> 

<!-- Silverlight Sleep API --> 
<object id="SleepSL" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="1" height="1"> 
    <param name="source" value="SleepSL.xap"/> 
    <param name="background" value="white" /> 
    <param name="minRuntimeVersion" value="4.0.50826.0" /> 
    <param name="autoUpgrade" value="true" /> 
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none"> 
     <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/> 
    </a> 
</object> 
<BR><BR> 

<DIV ID="clock"/> 
</BODY> 
</HTML> 

PauseWin.html

<html> 
<title>Pause Window</title> 
<style>body{margin-top:10}</style> 
<body scroll="no"> 

<center style='font-size:14px;font-weight:bold'> 
    The window will automatically <br> close in <span id="time"></span>&nbsp;second(s). 
</center> 

<script type="text/javascript"> 
    var ms = window.dialogArguments.SleepInterval; 

    function wait(){ 
     var span = document.getElementById('time'); 
     span.innerHTML = (ms/1000); 
     setInterval(function(){ closeWindow(); }, ms); 
     setInterval(function(){ ms -= 1000; if(ms > 0) span.innerHTML = (ms/1000); }, 1000); 
    } 

    function closeWindow(){ 
     window.close() 
    } 
    wait(); 
</script> 
</body> 
</html> 

通过执行index.html文件,我开始了一个YouTube视频和计时器。当我按下“暂停模态对话框”时,计时器停止,但视频继续播放,10秒后模态弹出窗口被JS“window.close()摧毁”,在我的代码中,我将进入下一行并执行alert (“简历”)。没有什么会改变视频继续播放。现在,如果我使用Silverlight Thread.Sleep函数按“暂停线程睡眠”按钮。此时视频将挂起,并通过单击Internet Explorer,您可能会在Process Explorer中看到(未响应)状态。

我更喜欢在COM,ActiveX或Silverlight对象中使用Thread.Sleep函数,但我需要删除线程死锁。获得与JavaScript模式对话框或警报中相同的行为。

非常感谢提前。

问候,

大卫Gofman

代码:

index.html

PauseWin.html

+0

您可以从http://code.google.com/p/flexdoor/sour下载silvelight代码和二进制文件ce/browse/trunk/html-template/App.xaml.cs http://code.google.com/p/flexdoor/source/browse/trunk/html-template/SleepSL.xap – 2011-03-14 18:11:00

+0

Internet Explorer以STAThread模式运行,所以本质上你完全阻止了它。我建议你分别使用COM和块,至少这就是我所做的。 – 2011-03-14 18:11:59

+0

我如何在COM中实现删除死锁?我会更喜欢C#或Silverlight代码。谢谢,大卫 – 2011-03-14 18:14:03

回答

1

您的代码做的正是你告诉它做的事:它睡你的浏览器UI线程,这意味着您的浏览器无法处理更多的消息,因此它有效地挂起我们的浏览器在睡眠期间。在浏览器中的Thread.Sleep()是死亡:不要在Silverlight或任何其他框架中执行此操作。

更好的方法是退后一步,问自己为什么要睡觉,然后找出合理的异步方式。在几年前被抛入Silverlight异步世界之后,我意识到这一开始可能会迷失方向,但我也可以证明,我总是找到相当干净的方法来做正确的事情。

另一种说法是:如果你无法弄清楚如何去做你真正需要做的事情,请发布一个关于的问题,,你可能会在这里得到一些帮助。

举例来说,如果你只是想等待“N”秒,然后进行回调,您可以使用一个辅助类,像这样的:

public class ThreadingHelper 
{ 
    public static void SleepAsync(int millisecondsToSleep, Action action) 
    { 
     var timer = new Timer(o => action()); 
     timer.Change(millisecondsToSleep, Timeout.Infinite); 
    } 

    public static void SleepAsync(TimeSpan interval, Action action) 
    { 
     SleepAsync((int)interval.TotalMilliseconds, action); 
    } 

    public static void DispatcherSleepAsync(int millisecondsToSleep, Action action) 
    { 
     var interval = TimeSpan.FromMilliseconds(millisecondsToSleep); 
     DispatcherSleepAsync(interval, action); 
    } 

    public static void DispatcherSleepAsync(TimeSpan interval, Action action) 
    { 
     var timer = new DispatcherTimer(); 
     EventHandler timerHandler = null; 
     timerHandler = (s, e) => 
     { 
      timer.Tick -= timerHandler; 
      if (action != null) 
      { 
       action(); 
      } 
     }; 
     timer.Tick += timerHandler; 
     timer.Interval = interval; 
     timer.Start(); 
    } 

} 
+0

嗨肯, 感谢您的意见。我不在寻找Aync解决方案。我可以在JavaScript中使用setInterval或setTimeout函数。我的目标是找到一个选项,我如何在运行时中断JavaScript执行并在稍后(10秒后)恢复。如果我不能在主线程中保存进程,可以打开不可分割的对话框或窗体并重定向JavaScript进程?与JavaScript alert或showModalDialog中的行为相同。 – 2011-03-15 04:18:52

1

你可以这样做:

function begin() { /* do stuff... */ } 
function afterWait() { /* rest of my code...*/ } 

begin(); 
setTimeout(afterWait, 10000);

setTimeout已有效遏制你的JavaScript 10秒,并在浏览器仍然可以继续工作