繁体   English   中英

我想制作自己的事件循环侦听器,但它阻塞了调用堆栈如何像处理任何事件一样处理它

[英]i want to make my own event loop listener but it is blocking the call stack how to handel it like any event

我希望我的代码检查数据是否发生变化然后做一些事情所以我想出了这个

 function autoRendring(list,unchangedlist){
    while(true){

        while(list==unchangedlist){
         //Busy waiting  
        }
          
        console.log("renderd !")
        render(list)
        unchangedlist=list
    }

我如何在不阻塞主线程的情况下执行此 fuchion 我已经阅读了有关事件循环以及浏览器如何将它们与主线程分开处理的信息,但我仍然不知道该怎么做

}

它只是阻塞主线程

我想在 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();

代码实际上存在多个问题:

您有两个嵌套的while循环,外部循环是一个无限循环,您可能已经猜到这是阻塞主线程,因为您的代码永远不会退出。 因此,无法执行其他可能导致任何更改甚至 UI 冻结的代码。

由于在执行外循环时不会发生任何变化,因此内循环中的条件不会发生变化,因此内循环也是无限的。

为此,您实际上必须让您的代码执行结束,以便事件循环可以继续,可以发生更改,然后您的代码必须再次调用以评估新的 state。

其次, list (和unchangedList )是 function 参数,因此在本地作用域为 function 因此,无法从 function 外部更改它们的值,并且更改它们的代码必须驻留在函数/相同的 scope 中。

要允许事件循环继续,您需要结束执行并将下一次代码执行排队。 您可以为此使用例如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);

使用 0ms 的间隔意味着“立即”执行回调——但仍然是异步的,即只将其放入队列并继续执行。 这允许事件循环执行其他队列回调(如果有的话)。

不过,与其一直执行回调,不如使用requestAnimationFrame来减少 CPU 负担。 这只会在绘制新帧之前对回调进行排队,这样效率更高,因为使用setInterval可以在实际绘制到屏幕之前多次重新渲染:

function autoUpdate() {
  if (list !== unchangedList) {
    render(list);
    unchangedList = list;
  }

  requestAnimationFrame(autoUpdate);
}
requestAnimationFrame(autoUpdate);

更有效的方法是仅在实际发生任何更改时才调用您的代码。 根据更改的来源,这可以通过适当的事件侦听器来完成,例如输入元素的change event或按钮和链接的click event

inputElement.addEventListener('change', () => render(inputElement.value));
buttonElement.addEventListener('click', () => {
  let list = getUpdatedList();
  render(list);
});

如果您想观察代码变量的变化,您可以使用RxJS等可观察对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM