簡體   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