C
C#16mo ago
yaro

✅ #async #Unity how to do something after tasks were complete and not block main threads with tasks

i have tasks that can take very log time to complete in unity and at the moment i launch tasks this way async void StartCuttingObjects() { foreach (var g in objectsToCut) { //i have removed some irrelevant code and if you wanna remove parameters in response it is fine var t = Task.Run(() => Cutter.AsyncCut(cutPlane, originalPos, originalRot, originalScale, mf, mr, mesh , subMeshCount, triangles, vertices, normals, uv, mats, g )); tasks.Add(t); } FooAsync(); } public async void FooAsync() { await Task.WhenAll(tasks); EndCuttingObjects(); }
59 Replies
Florian Voß
Florian Voß16mo ago
learn how to properly use async / await and Tasks a function that is async should always return Task unless its an event handler, only then async void is allowed and any async method should get awaited if you call without await then its not running asynchronously, its running synchronously and blocks your program async keyword doesnt make anything run asynchronously, await does async only allows you to use await in a method @yaroj3456
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
MODiX
MODiX16mo ago
TLDR on async/await: * every .net API that is suffixed with Async (eg: .Read() and .ReadAsync()) => use the Async version * if the API name ends with Async => await it * if the API returns a Task => await it * if you have to await in a method: * that method must have the async keyword (you could even suffix your function name with Async, up to you) * if it was returning T (eg:string) => it should now return Task<T> (eg: Task<string>) * APIs to ban and associated fix:
var r = t.Result; /* ===> */ var r = await t;
t.Wait(); /* ===> */ await t;
var r = t.GetAwaiter().GetResult(); /* ===> */ var r = await t;
Task.WaitAll(t1, t2); /* ===> */ await Task.WhenAll(t1, t2);
var r = t.Result; /* ===> */ var r = await t;
t.Wait(); /* ===> */ await t;
var r = t.GetAwaiter().GetResult(); /* ===> */ var r = await t;
Task.WaitAll(t1, t2); /* ===> */ await Task.WhenAll(t1, t2);
Florian Voß
Florian Voß16mo ago
do you have control over the command? could add that event handlers use async void only*
yaro
yaroOP16mo ago
changing public async void FooAsync() to public async Task FooAsync() didnt fix the issue
Florian Voß
Florian Voß16mo ago
well there is much more that I've said and the bot said - make same change on StartCuttingObjects - make sure any async method gets awaited, that includes Task.Run, FooAsync, StartCuttingObjects, all of these must get awaited
yaro
yaroOP16mo ago
i awaited that FooAsync and it didnt help if you are about that
Florian Voß
Florian Voß16mo ago
this
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
@TeBeClone he send this before reading my last message, give him some time to think about it
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
what implication? awaiting StartCuttingObjects?
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
ah that
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
I'm following, you got a point
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
StartCuttingObjects returning void?
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
we can assume its not a handler tho
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
I don't see what the void version provides to us other than the ability to block the program
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
my point is this is not a handler. I'm not aware of other cases where async void is fine, are there even any?
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
yeah
yaro
yaroOP16mo ago
did you mean await Parallel.ForEach( cause visual studio doesnt recognise foreachasync
Florian Voß
Florian Voß16mo ago
.net version?
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
what .net is unity using? I dont know game dev
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
even if its not actual async work the goal was to not block the main thread by scheduling the work on another thread so question should be answerd now by TeBeClone
yaro
yaroOP16mo ago
public static TaskResult AsyncCut(Plane cutPlane,
Vector3 originalPosition,
Quaternion originalRotation,
Vector3 originalScale,
MeshFilter originalMeshFilter, MeshRenderer originalMeshRenderer,
Mesh mesh,
int subMeshCount,
List<int[]> triangles
, Vector3[] vertices
, Vector3[] normals
, Vector2[] uv,
Material[] materials
, GameObject originalObject
)
public static TaskResult AsyncCut(Plane cutPlane,
Vector3 originalPosition,
Quaternion originalRotation,
Vector3 originalScale,
MeshFilter originalMeshFilter, MeshRenderer originalMeshRenderer,
Mesh mesh,
int subMeshCount,
List<int[]> triangles
, Vector3[] vertices
, Vector3[] normals
, Vector2[] uv,
Material[] materials
, GameObject originalObject
)
public class TaskResult
{
public GeneratedMesh leftMesh;
public GeneratedMesh rightMesh;
public Vector3 position;
public Quaternion rotation;
public Vector3 scale;
public Material[] materials;
public MeshFilter originalMeshFilter;
public MeshRenderer originalMeshRenderer;
public GameObject originalObject;
public TaskResult(GeneratedMesh leftMesh,
GeneratedMesh rightMesh,
Vector3 position,
Quaternion rotation,
Vector3 scale,
Material[] materials
, MeshFilter originalMeshFilter
, MeshRenderer originalMeshRenderer
, GameObject originalObject
)
{
this.leftMesh = leftMesh;
this.rightMesh = rightMesh;
this.position = position;
this.rotation = rotation;
this.scale = scale;
this.materials = materials;
this.originalMeshFilter = originalMeshFilter;
this.originalMeshRenderer = originalMeshRenderer;
this.originalObject = originalObject;
}
}
public class TaskResult
{
public GeneratedMesh leftMesh;
public GeneratedMesh rightMesh;
public Vector3 position;
public Quaternion rotation;
public Vector3 scale;
public Material[] materials;
public MeshFilter originalMeshFilter;
public MeshRenderer originalMeshRenderer;
public GameObject originalObject;
public TaskResult(GeneratedMesh leftMesh,
GeneratedMesh rightMesh,
Vector3 position,
Quaternion rotation,
Vector3 scale,
Material[] materials
, MeshFilter originalMeshFilter
, MeshRenderer originalMeshRenderer
, GameObject originalObject
)
{
this.leftMesh = leftMesh;
this.rightMesh = rightMesh;
this.position = position;
this.rotation = rotation;
this.scale = scale;
this.materials = materials;
this.originalMeshFilter = originalMeshFilter;
this.originalMeshRenderer = originalMeshRenderer;
this.originalObject = originalObject;
}
}
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
yeah
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
wait
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
yaro
yaroOP16mo ago
no it is my custom made task
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
LoL okay I just thought for a sec they dont use TPL yikes
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
yaro
yaroOP16mo ago
yeah cpu bound no io
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
I agree
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
make even AsyncCut synchronous and just wrap in Task.Run if its just cpu bound
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
but should be not at least await Task.Run @TeBeClone ? you know better then me, I'm just asking no critique
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
fair
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
just that StartCuttingObjects is now blocking ^^ it shouldnt be tho or why would we use Task.Run() in the first place. Or do I have a brain fart here @TeBeClone
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
I mean the ultimate goal was to write non blocking code and this looks very blocking to me
yaro
yaroOP16mo ago
,well initially there was a task.run
foreach (var g in objectsToCut)
{
print(g);
Vector3 position = transform.position;
Vector3 originalPos = g.transform.position;
Vector3 originalScale = g.transform.localScale;
Quaternion originalRot = g.transform.rotation;
var mf = g.transform.GetComponent<MeshFilter>();
var mr = g.transform.GetComponent<MeshRenderer>();
var mesh = mf.mesh;
var subMeshCount = mesh.subMeshCount;
var triangles = new List<int[]>();
var vertices = mesh.vertices;
var normals = mesh.normals;
var uv = mesh.uv;
var mats = mr.materials;
for (int i = 0; i < subMeshCount; i++)
{
triangles.Add(mesh.GetTriangles(i));
}
Plane cutPlane = new(g.transform.InverseTransformDirection(cutNormal), g.transform.InverseTransformPoint(position));
var t = Task.Run(() => Cutter.AsyncCut(cutPlane,
originalPos,
originalRot,
originalScale,
mf,
mr,
mesh
, subMeshCount,
triangles,
vertices,
normals,
uv,
mats,
g
));
tasks.Add(t);

}
foreach (var g in objectsToCut)
{
print(g);
Vector3 position = transform.position;
Vector3 originalPos = g.transform.position;
Vector3 originalScale = g.transform.localScale;
Quaternion originalRot = g.transform.rotation;
var mf = g.transform.GetComponent<MeshFilter>();
var mr = g.transform.GetComponent<MeshRenderer>();
var mesh = mf.mesh;
var subMeshCount = mesh.subMeshCount;
var triangles = new List<int[]>();
var vertices = mesh.vertices;
var normals = mesh.normals;
var uv = mesh.uv;
var mats = mr.materials;
for (int i = 0; i < subMeshCount; i++)
{
triangles.Add(mesh.GetTriangles(i));
}
Plane cutPlane = new(g.transform.InverseTransformDirection(cutNormal), g.transform.InverseTransformPoint(position));
var t = Task.Run(() => Cutter.AsyncCut(cutPlane,
originalPos,
originalRot,
originalScale,
mf,
mr,
mesh
, subMeshCount,
triangles,
vertices,
normals,
uv,
mats,
g
));
tasks.Add(t);

}
but on smartphone there is always a lag when I start cutting
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß16mo ago
public async Task CutObjects(){
await Task.Run(() => {
Parallel.ForEach(objectrsToCut, (_) => Cutter.Cut())
});
}
public async Task CutObjects(){
await Task.Run(() => {
Parallel.ForEach(objectrsToCut, (_) => Cutter.Cut())
});
}
From my understanding this would be best for @yaroj3456 The Cut method is synchronous cuz its nothing that would require asynchronous working. But we wrap it in something non blocking to not block main thread?
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Want results from more Discord servers?
Add your server