[英]i want to make my own event loop listener but it is blocking the call stack how to handel it like any event
i want my code to chick if a data is changed and then do some thing so i came up with this我希望我的代码检查数据是否发生变化然后做一些事情所以我想出了这个
function autoRendring(list,unchangedlist){
while(true){
while(list==unchangedlist){
//Busy waiting
}
console.log("renderd !")
render(list)
unchangedlist=list
}
how can i execute this fuchion with out blocing the main thread i have read about the event loops and how the browser handel them Separately from the main thead but i still dont know what to do我如何在不阻塞主线程的情况下执行此 fuchion 我已经阅读了有关事件循环以及浏览器如何将它们与主线程分开处理的信息,但我仍然不知道该怎么做
} }
it just block the main thread它只是阻塞主线程
i want to make some thing like this in c#我想在 c# 中做这样的事情
using System.Threading;
int x = 0;
int y = x;
Thread t = new Thread(() => render(ref x,ref y));
Thread t2 = new Thread(() => change(ref x,ref y));
static void render(ref int x,ref int y)
{
while (true)
{
while (x == y)
{
}
Console.WriteLine(" x has changed and renderd !");
y=x;
}
}
static void change(ref int x,ref int y)
{
while (true)
{
Console.WriteLine("inter x ");
Console.WriteLine("x is " + x + " and y is " + y);
x = int.Parse(Console.ReadLine());
}
}
t2.Start();
t.Start();
There are actually multiple issues with the code:代码实际上存在多个问题:
You have two nested while
loops, the outer one is an infinite loop, and as you already might have guessed this is blocking main thread since your code does never exit.您有两个嵌套的
while
循环,外部循环是一个无限循环,您可能已经猜到这是阻塞主线程,因为您的代码永远不会退出。 Thus no other code can be executed which could cause any change and even the UI freezes.因此,无法执行其他可能导致任何更改甚至 UI 冻结的代码。
Since no change can happen while executing the outer loop the condition in the inner loop will not change and so the inner loop is infinite too.由于在执行外循环时不会发生任何变化,因此内循环中的条件不会发生变化,因此内循环也是无限的。
For this to work you actually have to let your code execution end so the event loop can continue, changes can happen, and then your code has to be called again to evaluate the new state.为此,您实际上必须让您的代码执行结束,以便事件循环可以继续,可以发生更改,然后您的代码必须再次调用以评估新的 state。
Second, list
(and unchangedList
) are function parameters and so scoped locally to the function .其次,
list
(和unchangedList
)是 function 参数,因此在本地作用域为 function 。 Because of this there is no way of changing their value from outside of the function and code changing them must reside within the function/same scope.因此,无法从 function 外部更改它们的值,并且更改它们的代码必须驻留在函数/相同的 scope 中。
To allow the event loop to continue you need to end your execution and queue the next execution of your code.要允许事件循环继续,您需要结束执行并将下一次代码执行排队。 You could use for example
setInterval
for this:您可以为此使用例如
setInterval
:
let list;
let unchangedList;
// initialize `list` here
// some example on how `list` could be updated
button.addEventListener('click', () => {
// update `list`
});
function autoUpdate() {
if (list !== unchangedList) {
render(list);
unchangedList = list;
}
}
setInterval(autoUpdate, 0);
Using an interval of 0ms means to execute the callback "immediately" - but still asynchronously, ie, only to put it in the queue and continue execution.使用 0ms 的间隔意味着“立即”执行回调——但仍然是异步的,即只将其放入队列并继续执行。 This allows the event loop to execute other queue callbacks if there are any.
这允许事件循环执行其他队列回调(如果有的话)。
Instead of executing your callback all the time though, a less CPU-heavy approach would be using requestAnimationFrame
.不过,与其一直执行回调,不如使用
requestAnimationFrame
来减少 CPU 负担。 This will queue your callback only evertime before a new frame is painted which is more efficient since with setInterval
you could re-render multiple times before it is actually painted to the screen:这只会在绘制新帧之前对回调进行排队,这样效率更高,因为使用
setInterval
可以在实际绘制到屏幕之前多次重新渲染:
function autoUpdate() {
if (list !== unchangedList) {
render(list);
unchangedList = list;
}
requestAnimationFrame(autoUpdate);
}
requestAnimationFrame(autoUpdate);
Even more efficient would be to call your code only if there actually is any change.更有效的方法是仅在实际发生任何更改时才调用您的代码。 Depending on the source of your change this could be done with appropriate event listeners like the
change event
of input elements or the click event
for buttons and links:根据更改的来源,这可以通过适当的事件侦听器来完成,例如输入元素的
change event
或按钮和链接的click event
:
inputElement.addEventListener('change', () => render(inputElement.value));
buttonElement.addEventListener('click', () => {
let list = getUpdatedList();
render(list);
});
If you want to observe changes in your code's variables you maybe could use observables such as with RxJS
.如果您想观察代码变量的变化,您可以使用
RxJS
等可观察对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.