Back to Writing
NOTESunityjob-systemmultithreadingasynccsharp

Unity Job System Explained

June 13, 2020Updated Feb 17, 2026

![](

kg.7MqeiDUVl82sG1zO5Jbat4ZZ7fP1PG58hx_t-ouZQFog.PNG.cdw0424/SE-80f52106-4555-4db1-be5f-7f20a16e0128.png?type=w966)

Calling Complete() on a handle within a single function like this will stall the main thread.

This means issues like buttons freezing when pressed will occur.

(Complete() is more accurately described as a "wait" — similar to await.)

![](

wg.AOQx2lZnAjDssoCccq__LwEMCmEC73Ol8WIjGhY7k3Qg.PNG.cdw0424/SE-ddddb174-c575-43bb-ba8c-7d67b00db0ff.png?type=w966)

If the job is a very simple task and the result is expected within a single frame, you can simply skip one frame and wait for completion. But if the job is larger and you're doing truly asynchronous coding:

![](

5wPERPRYLmcGsBxZvAg.6RsBSfz_PkxORHv9rbjsmWhxFFLmyvE5wDrHW88BlYAg.PNG.cdw0424/image.png?type=w966)

If the job hasn't completed yet, use the IsCompleted property to pass it to the next frame. (It's good practice to call Complete() at the end to ensure the job has definitively finished.)

![](

_gpuM3E6yvIOlyYAv8g.JUWsC_6qhQF-RNF64qTTUEgdE-qI7THd3KmentZnFoEg.PNG.cdw0424/image.png?type=w966)

Otherwise, a single frame can become very long and performance will degrade.

Remember that in the Job System, processing happens on other threads but results are ultimately handled on the main thread. If you don't keep this in mind, you won't experience the benefits of the Job System.

Test Code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Jobs;

public class Test : MonoBehaviour
{
JobHandle handle;
int i;

// Start is called before the first frame update
void Start()
{
i = 0;
StartCoroutine(CoTest());      
}

private void Update()
{
print("Frame: " + i++);
}

IEnumerator CoTest()
{
yield return null;

TestJob testJob;
handle = testJob.Schedule();

print(handle.IsCompleted);      

// To test, leave yield return null; just remove the While section.
while(!handle.IsCompleted)
{
yield return null;
}

handle.Complete();

print(handle.IsCompleted + "----------------------------------------------------------------------------");
}
   
struct TestJob : IJob
{
public void Execute()
{
for (int i = 0; i < 10000; i++)
{
print(i);
}
}
}
}