Remove a dead lock in the Internet Explorer on Thread.Sleep?
I know all browsers are single threaded and impossible implements in JavaScript or Flash Player Thread.sleep. I decided to try using “System.Threading” library implements Thread.Sleep in the Silverlight.
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);
}
}
}
So, from a JavaScript code I can execute a Sleep function, but my Internet Explorer freeze and not responding.
Here is my example:
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='fon开发者_开发问答t-size:14px;font-weight:bold'>
The window will automatically <br> close in <span id="time"></span> 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>
By executing an index.html file I am starting a YouTube video and timer. When I pressed "Pause Modal Dialog" the timer stops, but video continue playing, after 10 seconds the Modal Popup window destroying by JS “window.close()” and in my code I am going to the next line and executing alert(“Resume”). Nothing change the video continues playing. Now if I will press "Pause Thread Sleep" button using a Silverlight Thread.Sleep function. At this time video will hang and by clicking on the Internet Explorer you may get (Not Responded) state in the Process Explorer.
I will prefer to use Thread.Sleep function in the COM, ActiveX or Silverlight objects, but I need to remove that a thread dead lock. Get the same behavior as in JavaScript Modal Dialog or Alert.
Many thanks in advance.
Regards,
David Gofman
Code:
index.html
PauseWin.html
Your code is doing exactly what you're telling it to do: it's sleeping your browser's UI thread, which means that your browser can't process any more messages, so it's effectively hanging your browser for the duration of the sleep. Thread.Sleep() in a browser is death: just don't do it, whether in Silverlight or any other framework.
A better approach would be to step back and ask yourself why you want to sleep something, and then figure out a reasonable async way of doing that. Having been thrown into the Silverlight async world several years ago, I realize that this can be disorienting at first, but I can also testify that I've always found reasonably clean ways to do it right.
Another way to put it: if you can't figure out how to do what it is that you actually need to get done, post a question about that, and you'll likely get some help here.
For instance, if you just want to wait 'n' seconds and then perform a callback, you could use a helper class like this one:
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();
}
}
You could do this:
function begin() { /* do stuff... */ } function afterWait() { /* rest of my code...*/ } begin(); setTimeout(afterWait, 10000);
setTimeout
has effectively stopped your javascript for 10 seconds, and the browser can still carry on working
精彩评论