2011-03-14 54 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秒,並在瀏覽器仍然可以繼續工作