Search code examples
web-worker

Does web worker block on the main thread for some OffscreenCanvas functions?


I have a web worker processing an array of saved ImageData frames and am using an OffscreenCanvas's context (created in the web worker) to putImageData. Meanwhile in my main thread I block on another operation. If I include the context.putImageData() call, the web worker blocks until my main thread completes before continuing, but if I remove the putImageData call or use context.clearRect() the web worker will run concurrently with my main thread.

Even if I'm running in a web worker, is it possible that the web worker blocks on some uses of OffscreenCanvas? This also happens with convertToBlob.


Solution

  • It shouldn't.

    But there is indeed a regression caused by this issue, which affects Chrome > 82.

    I did open a bug report, so now all we can do is to wait for them to fix it.

    Here is the MCVE I produced:

    const worker_script = `
    postMessage('ready'); // main will block
    const now = performance.now();
    const off = new OffscreenCanvas(300, 150);
    const off_ctx = off.getContext('2d');
    off_ctx.fillRect(0,0,30,30)
    postMessage( performance.now() - now );
    `;
    const worker_url = URL.createObjectURL( new Blob( [ worker_script ], { type: "text/javascript" } ) );
    const worker = new Worker( worker_url );
    
    worker.onmessage = evt => {
      if (evt.data === "ready" ) {
        blockMainThread( 3000 )
          .then( () => log( 'now free' ) );
      }
      else log( `worker script took ${evt.data}ms to complete.` );
    };
    
    worker.postMessage( "" );
    
    function blockMainThread( duration ) {
      return new Promise( ( resolve ) => {
        const now = performance.now();
        while( performance.now() - now < duration ) {}
        resolve();
      } );
    }
    function log( content ) {
      _log.textContent += content + '\n';
    }
    <pre id="_log">
    The page will be frozen for 3s. Please wait.
    </pre>

    Given the nature of that bug, I doubt there is any way to workaround it.