Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Async/await and webgl builds

Discussion in 'Experimental Scripting Previews' started by kiyakkoray, May 27, 2017.

  1. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    Hello,
    I'm not sure if this fits to here but im writing anyway:)
    I have just started to test new 2017.1 builds to see how goes the new scripting stuff. I have tried to make some async methods which works fine on standalone builds. But when i try to build it using webgl, async methods doesnt seems to continue after awaited task finishes. Is this a known issue or am i making something wrong?
     
    _TheFuture_ likes this.
  2. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    It really depends on how to are using async and await. If this involves more than one thread, this won't work on WebGL, as threads are not supported there. I don't think that anything on Unity end should use more than one thread. Can you provide more details about the code that is causing the issue?
     
  3. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    Here is a code piece that works on standalone players but not on webgl.
    Code (CSharp):
    1. using System.Threading.Tasks;
    2. using UnityEngine;
    3.  
    4. class ExampleAsyncAwait : MonoBehaviour
    5. {
    6.     void Start()
    7.     {
    8.         Task testTask = TestMethod();
    9.     }
    10.  
    11.     async Task TestMethod()
    12.     {
    13.         Debug.Log("First hello");
    14.         await Task.Delay(1000);
    15.  
    16.         Debug.Log("Second hello");
    17.         await Task.Delay(1000);
    18.  
    19.         Debug.Log("Third hello");
    20.         await Task.Delay(1000);
    21.  
    22.         Debug.Log("Yet another hello");
    23.         await Task.Delay(1000);
    24.  
    25.         Debug.Log("Finished");
    26.     }
    27. }
    28.  
    Actually it must be no different then coroutines but with nice syntax using the synchronization context provided by unity itself.
     
  4. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    I have replaced delays with yields and it seemed to work. It could be possible that those delay tasks are not implemented on webgl.
     
  5. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
  6. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    Thanks for your time. I have just implemented a custom task to make delayed yields. It would be nice if unity provides these by itself like the ones(WaitForSeconds etc...) we use for coroutines.

    Anyway i have a second question:) Here is a simple code that shows the problem...

    Code (CSharp):
    1. using System.Threading.Tasks;
    2. using UnityEngine;
    3.  
    4. class ExampleAsyncAwait : MonoBehaviour
    5. {
    6.     void Start()
    7.     {
    8.         Task testTask = TestMethod();
    9.     }
    10.  
    11.     async Task TestMethod()
    12.     {
    13.         Dummy testObject = await TestSubMethod<Dummy>();
    14.         Debug.Log("This line will not execute");
    15.         Debug.Log(testObject);
    16.     }
    17.  
    18.     async Task<T> TestSubMethod<T>() where T : class, new()
    19.     {
    20.         T result = new T();
    21.         await TestSubMethod2();
    22.         Debug.Log("This line will be executed");
    23.  
    24.         return result;
    25.     }
    26.  
    27.     Task TestSubMethod2()
    28.     {
    29.         Debug.Log("Just a dummy log");
    30.         return Task.FromResult(0);
    31.     }
    32. }
    33.  
    34. class Dummy
    35. {
    36.     public Dummy()
    37.     {
    38.      
    39.     }
    40. }
    41.  
    This code works fine on standalone players. But at webgl I can't see the "This line will not execute" comment on console. It seems to be a problem related with generics and async combination. But i'm not sure.

    Currently i'm implementing my method with every possible type which i use to avoid this. Any ideas?
     
    Last edited: May 31, 2017
  7. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    Can you provide the full output you get from the standalone and WebGL players? I'm not sure why there is a difference.
     
  8. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    Here goes the full logs

    index.html:8 Resource interpreted as Stylesheet but transferred with MIME type text/plain: "http://localhost:8080/Immersion.WebGL/TemplateData/style.css".
    UnityLoader.js:234 run() called, but dependencies remain, so not running
    printErr @ UnityLoader.js:234
    run @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441278
    UnityLoader.da1f3f68d9e4c7fa12541611c3cd53e0 @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441366
    UnityLoader.loadCode.Module @ UnityLoader.js:95
    script.onload @ UnityLoader.js:26
    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:444 [Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
    read @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:444
    loadDynamicLibrary @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:658
    (anonymous) @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:1580
    (anonymous) @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:1579
    callRuntimeCallbacks @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:1325
    preRun @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:1354
    run @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441282
    runCaller @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441235
    removeRunDependency @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:1570
    applyMemoryInitializer @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441197
    useRequest @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441212
    UnityLoader.js:234 pre-main prep time: 9355 ms
    printErr @ UnityLoader.js:234
    doRun @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441292
    run @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441307
    runCaller @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:441235
    removeRunDependency @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:1570
    (anonymous) @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:11
    doCallback @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:5591
    done @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:5602
    done @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:4715
    storeLocalEntry @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:4633
    (anonymous) @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:4726
    UnityLoader.da1f3f68d9e4c7fa12541611c3cd53e0.IDBFS.loadRemoteEntry.req.onsuccess @ blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:4652
    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 PlayerConnection initialized from (debug = 0)

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 PlayerConnection disabled - listening mode not supported

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 Initialize engine version: 2017.1.0b6 (38ec4e48ade7)

    UnityLoader.js:233 Creating WebGL 2.0 context.
    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 Renderer: WebKit WebGL

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 Vendor: WebKit

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 Version: OpenGL ES 3.0 (WebGL 2.0 (OpenGL ES 3.0 Chromium))

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 GLES: 3

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 EXT_color_buffer_float GL_EXT_color_buffer_float EXT_disjoint_timer_query_webgl2 GL_EXT_disjoint_timer_query_webgl2 EXT_texture_filter_anisotropic GL_EXT_texture_filter_anisotropic OES_texture_float_linear GL_OES_texture_float_linear WEBGL_compressed_texture_s3tc GL_WEBGL_compressed_texture_s3tc WEBGL_debug_renderer_info GL_WEBGL_debug_renderer_info WEBGL_debug_shaders GL_WEBGL_debug_shaders WEBGL_lose_context GL_WEBGL_lose_context

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 OPENGL LOG: Creating OpenGL ES 3.0 graphics device ; Context level <OpenGL ES 3.0> ; Context handle 1

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 UnloadTime: 25.960000 ms

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 Just a dummy log

    (Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/WebGL/runtime/DebugBindings.gen.cpp Line: 51)


    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 This line will be executed

    (Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/WebGL/runtime/DebugBindings.gen.cpp Line: 51)


    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:5584 warning: 2 FS.syncfs operations in flight at once, probably just doing extra work
    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:5584 warning: 2 FS.syncfs operations in flight at once, probably just doing extra work
    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:5584 warning: 2 FS.syncfs operations in flight at once, probably just doing extra work

    Mono path[0] = 'E:/Develop/Immersion.Binary/Immersion_Data/Managed'
    Mono config path = 'E:/Develop/Immersion.Binary/Immersion_Data/MonoBleedingEdge/etc'
    PlayerConnection initialized from E:/Develop/Immersion.Binary/Immersion_Data (debug = 0)
    PlayerConnection initialized network socket : 0.0.0.0 55198
    Multi-casting "[IP] 192.168.1.247 [Port] 55198 [Flags] 2 [Guid] 3289737884 [EditorId] 1575425679 [Version] 1048832 [Id] WindowsPlayer(KORAY-PC) [Debug] 0" to [225.0.0.222:54997]...
    Started listening to [0.0.0.0:55198]
    PlayerConnection already initialized - listening to [0.0.0.0:55198]
    Player data archive not found at `E:/Develop/Immersion.Binary/Immersion_Data/data.unity3d`, using local filesystemInitialize engine version: 2017.1.0b6 (38ec4e48ade7)
    GfxDevice: creating device client; threaded=1
    Direct3D:
    Version: Direct3D 11.0 [level 11.1]
    Renderer: NVIDIA GeForce GTX 1080 (ID=0x1b80)
    Vendor: NVIDIA
    VRAM: 8110 MB
    Driver: 21.21.13.7892
    Begin MonoManager ReloadAssembly
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\UnityEngine.dll into Unity Child Domain
    Platform assembly: E:\Develop\Immersion.Binary\Immersion_Data\Managed\System.Core.dll (this message is harmless)
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\Assembly-CSharp-firstpass.dll into Unity Child Domain
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\Assembly-CSharp.dll into Unity Child Domain
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\UnityEngine.UI.dll into Unity Child Domain
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\UnityEngine.Networking.dll into Unity Child Domain
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\UnityEngine.Timeline.dll into Unity Child Domain
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\UnityEngine.Analytics.dll into Unity Child Domain
    Loading E:\Develop\Immersion.Binary\Immersion_Data\Managed\Newtonsoft.Json.dll into Unity Child Domain
    Platform assembly: E:\Develop\Immersion.Binary\Immersion_Data\Managed\System.dll (this message is harmless)
    - Completed reload, in 0.289 seconds
    <RI> Initializing input.

    XInput1_3.dll not found. Trying XInput9_1_0.dll instead...
    <RI> Input initialized.

    <RI> Initialized touch support.

    UnloadTime: 0.714602 ms
    Just a dummy log
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    ExampleAsyncAwait:TestSubMethod2() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:29)
    <TestSubMethod>c__async1`1:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:21)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:Start(<TestSubMethod>c__async1`1&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:471)
    ExampleAsyncAwait:TestSubMethod()
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:13)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 471)

    This line will be executed
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    <TestSubMethod>c__async1`1:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:22)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:Start(<TestSubMethod>c__async1`1&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:471)
    ExampleAsyncAwait:TestSubMethod()
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:13)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 471)

    This line will not execute
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:14)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 316)

    Dummy
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:15)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 316)

    Setting up 4 worker threads for Enlighten.
    Thread -> id: 4350 -> priority: 1
    Thread -> id: 7aa8 -> priority: 1
    Thread -> id: a71c -> priority: 1
    Thread -> id: 5c58 -> priority: 1
     
  9. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    Smaller logs if you wish to see;

    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 Just a dummy log

    (Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/WebGL/runtime/DebugBindings.gen.cpp Line: 51)


    blob:http://localhost:8080/d8398a8e-4e84-46f6-a460-e7776dcffabb:9301 This line will be executed

    (Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/WebGL/runtime/DebugBindings.gen.cpp Line: 51)

    Just a dummy log
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    ExampleAsyncAwait:TestSubMethod2() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:29)
    <TestSubMethod>c__async1`1:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:21)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:Start(<TestSubMethod>c__async1`1&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:471)
    ExampleAsyncAwait:TestSubMethod()
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:13)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 471)

    This line will be executed
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    <TestSubMethod>c__async1`1:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:22)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:Start(<TestSubMethod>c__async1`1&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:471)
    ExampleAsyncAwait:TestSubMethod()
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:13)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 471)

    This line will not execute
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:14)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 316)

    Dummy
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    <TestMethod>c__async0:MoveNext() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:15)
    System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start(<TestMethod>c__async0&) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:316)
    ExampleAsyncAwait:TestMethod()
    ExampleAsyncAwait:Start() (at E:\Develop\Immersion\Immersion.Unity\Assets\Sources\ExampleAsyncAwait.cs:8)

    (Filename: /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs Line: 316)
     
    Last edited: May 31, 2017
  10. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    Thanks for the details. Indeed, it seems that
    Code (CSharp):
    1. await TestSubMethod<Dummy>();
    never continues. I think this should work in WebGL, so this looks like a bug. Do you mind submitting a bug report with this project? I'd like to take a look at it here.
     
  11. kiyakkoray

    kiyakkoray

    Joined:
    Jan 29, 2017
    Posts:
    8
    Posted a bug report using Unity. Case number is 916582.
    Thanks for your time :)
     
  12. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    Thanks, we will investigate this.
     
  13. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,499
  14. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    Unfortunately, this bug has reappeared. Tested in Unity 2019.3.9f1 w/ WASM threading enabled. Opened as case #1243010. The reproduction code is very simple.

    Code (CSharp):
    1.  private void Start()
    2.     {
    3.         LogThreadSafe("Start");
    4.      
    5.         Task task1 = Task.Run(() =>
    6.         {
    7.             LogThreadSafe("task1.Run()");
    8.         });
    9.  
    10.         Task task2 = Task.Run(async () =>
    11.         {
    12.             await Task.Delay(1);
    13.             LogThreadSafe("task2.Run() - Async");
    14.         });
    15.  
    16.         Task.WhenAll(task1, task2);
    17.      
    18.         LogThreadSafe("Stop");
    19.     }


    Gist: https://gist.github.com/stonstad/bf0de9cb7e77096c9600a652a74be3db
     
  15. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    I have a separate issue opened w/ Unity regarding ConcurrentDictionary. Switching the above example from ConcurrentQueue to Queue does not change the behavior. Tasks still don't run.
     
    ashwani_9 likes this.
  16. Katoha

    Katoha

    Joined:
    Feb 17, 2020
    Posts:
    5
  17. ashwani_9

    ashwani_9

    Joined:
    Mar 31, 2019
    Posts:
    6
    Hi @JoshPeterson

    I'm trying to integrate the addressable asset into the WebGL project and facing some serious issues like-
    1. Not able to play audio/video using addressable.
    2. not able to make an asset bundle addressable that was built on another project.
    3. What's the alternate of AsynOperationHandle while working on WebGL platform.
     
  18. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    Sorry, I'm pretty unfamiliar with addressables, so I'm likely not the right person to help here.
     
  19. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    @JoshPeterson Is there any sense of urgency around WebGL threading issues? Similarly, my mind is blown that ConcurrentDictionary.Count causes the WebGL player to crash.
     
    _TheFuture_ and ashwani_9 like this.
  20. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    I'm unaware of any specific but reports for WebGL related to threading issues, but the WebGL team may have some. I'm not sure what the roadmap is for supporting threads in WebGL using shared array buffers, but again, I'm not directly involved there.

    I'd recommend that you submit a bug report about ConcurrentDictionary.Count. Are there any other issues that should be addressed?
     
  21. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    Josh, I reported both but it seems like there is no activity from QA/Dev other than to confirm the behavior. It's in a holding pattern of sorts -- despite the severity of the issues.

    1243010 (Regression) Async Tasks Do Not Run on WebGL w/ Threading Enabled

    1243361 (Open) WebGL Blows up on ConcurrentDictionary.Count
     
  22. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    It looks like both are currently with our WebGL team. I'll ask about them.
     
    stonstad likes this.
  23. jason_skillman

    jason_skillman

    Joined:
    Feb 1, 2020
    Posts:
    11
    Hello, I too have been working with Addressables in WebGL and am having similar issues. I was able to get AsynOperationHandle to work in a Coroutine but it is still slow and unstable. I ended up having to abandon Addressables on WebGL as it is just not stable.
     
    d1favero likes this.
  24. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
  25. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    Our WebGL team is investigating both issues. I don't have any more details about them at the moment though.
     
  26. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    I have a fix for `1243010 (Regression) Async Tasks Do Not Run on WebGL w/ Threading Enabled` being reviewed now.
     
  27. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    Awesome, thank you so much!
     
  28. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    There are still a lot of problems with WebGL threads we're trying to work through. Anything that locks the main thread, like Task.Wait*, browsers really don't like at all and it will lock the page. There are some work-arounds for code you're in control of, like using `await Task.When*` instead. But it's a significant problem we are aware and is due to how threads are handled in browsers. That, and currently only Chrome (and now probably Edge) have threading support enabled by default.
     
  29. KevinCodes4Food

    KevinCodes4Food

    Joined:
    Dec 6, 2013
    Posts:
    61
    We'd be O.K. with these limitations, especially if we can detect them, work around them, and/or notify customers in our apps to turn on threads in the browser.

    Any possibility of being able to test or preview WebGL threads to start seeing how they impact our games?
     
  30. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    I have the fix in the main code branch, but I checked the current alpha 2020.2.a15 and don't see the fix. I'm not sure what the release schedule is, but I would expect soon. I can probably get it back-ported to the other versions, too.
     
  31. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    @brendanduncan_u3d It would be important to see this fix in 2019.4 LTS. Otherwise, we would have to wait six months upwards to a year to see it become available in a non-beta release.
     
    luca_digennaro likes this.
  32. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    The backport was submitted for 2020.1. I'll check in on 2019, not sure why that wasn't included
     
  33. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    Hey @brendanduncan_u3d I'm interested in knowing if you found out whether this will make it to 2019.4 LTS. We tested our project with 2020.2 and WebGL build bugs are preventing us from testing and moving forward. We're stuck on this particular issue ATM because of no release build contains the fix.
     
  34. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    I'm looking forward to this fix. I see it is in 2020.1.0.b17 which looks to drop soon. For 2020.2.0a18 it might work but I hit other errors with the WebGL build process.
     
  35. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    The backport was just finished for 2019.4. The backport still needs to get pushed into the main 2019 branch, and I don't know what the release version update schedule is, but it should be soon.
     
    De-Panther likes this.
  36. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    @brendanduncan_u3d It looks like it did not make it into 2020.1.0.... should it be in there?
     
  37. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    I just looked at the 2020.1 release code branch and you're right, the code change isn't there. I dug up the PR the backport team had submitted, and it was approved but never merged. I suspect they were holding off on merging backports until it shipped, to avoid potential instabilities. I'll ask around about when we can expect PRs to get merged.
     
  38. brendanduncan_u3d

    brendanduncan_u3d

    Unity Technologies

    Joined:
    Jul 30, 2019
    Posts:
    359
    So I have some bad news. I'm going to have to pull out the change enabling user defined threads. There are a lot of issues with WASM threads, particularly with garbage collection and managed objects, that it creates a very unstable environment. We are investigating options to support user defined threads. Currently, enabling threading will only be used to spawn some internal engine threads for improving performance in some cases, which can be managed correctly, but doesn't work for C# threads. I know this is disappointing, but we will work on finding a threading solution that works with managed code and Web Assembly.
     
    _TheFuture_, GCatz and De-Panther like this.
  39. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    Brendan, I appreciate the communication. Yep, it is definitely disappointing and it has a sizable impact on our project. I recall threading working in WebGL circa Unity 2018.x ... before the feature was disabled due to browser-based security issues. This was quite a while ago and my memory is hazy.

    These things happen. What is surprising to me is that there is impact on the overall runtime. User threads that do not touch game engine components (i.e. spinning off a thread to execute a pure math algorithm) seem like the safest category of threading. Just curious -- WASM exposes a pthread implementation and what does Unity use?
     
  40. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    Let me follow up with a bit more detail about why this won't work. Unity's managed garbage collector requires a few things from the OS or platform:
    • It must be able to suspend and resume all threads
    • It must be able to access the stack so that it can scan local variables for managed objects
    Wasm doesn't provide support for either of these operations. It is possible for IL2CPP to work around both of the limitations (at some performance cost), but we've not implemented those work arounds yet. We may implement them in the future, but we'll need to understand the performance trade-off first.

    I don't believe that Unity WebGL ever supported managed code on threads, or at least, had never solved this two issues. It is true that most browsers supported Wasm threads, but then had to disable support due to Spectre-like security issues. Now that those security issues have been mitigated, it is our hope that we can being managed threads to WebGL in Unity.
     
    MisfitXXX, GCatz and bdovaz like this.
  41. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    DrViJ likes this.
  42. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
  43. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,806
    That issue was corrected a while ago, but the issue was a more general one that occurs on both WebGL and platforms that support threads. So we fixed it, but it still does not indicate that user threads work with WebGL have either asmjs or Wasm.
     
  44. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    I converted all usage of System.Threading.Tasks.Task to UniTask (https://github.com/Cysharp/UniTask). This allows me to run through all workflows in the WebGL player. However, crashes occur inconsistently, with very nebulous stack traces that make it hard to pinpoint the associated line of code. To be certain, I went through all dependent libraries and source to make sure all System.Threading.Task dependencies were eliminated. The fact that it can work, but just fails frequently, shows me I am still experiencing a threading/race-condition-like issue.

    I'm turning on threading for WASM output builds so that I may use the async keyword, which is required by UniTask. One theory that I'm working with is that the internal threading you mentioned, used by Unity when this flag is enabled, is also unstable.
     
    arielfel likes this.
  45. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    I have all threading code (system.threading, system.threading.tasks) removed. I do enable the WASM multithreading flag for async/await keyword support via UniTask. (async/await does not imply multi-threading).

    The cause of instability I am seeing in WebGL WASM w/ threading enabled is directly related to usage of ConcurrentQueue, ConcurrentDictionary, and ConcurrentList. Access to these collections randomly fails in a single threaded context.

    I don't know whether this is possible or whether it even makes sense. Experimentally, that is what I found and once I switched to thread unsafe collections the random WebGL player errors went away (WebGL error: Uncaught RuntimeError: memory access out of bounds).

    Originally, I kept these collections around because they were used in a multithreaded context within the stand-alone player.
     
    DrViJ likes this.
  46. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    154
    Last edited: Aug 17, 2020
  47. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    I'm getting the same compile error in 2020.1.2. Thank you for your post @DrViJ I was confused by these new IL2CPP compilation errors and I hadn't connected it with the upgrade. I reverted to 2020.1.0 and it is compiling again. I sincerely hope threading in WebGL is getting the love and attention it needs at Unity.
     
  48. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    604
    @DrViJ how is your runtime stability w/ the WebGL player? I get frequent random crashes. Some were caused by use of concurrent collections -- but I have a few remaining that I can't pinpoint the cause of. One occurred inside a call stack for when material/shader properties are applied by the engine, which leads me to suspect that Unity internal threading might be bugged.
     
  49. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    154
    @stonstad, Our WebGL with synchronous execution are very stable at work. We are using Unity Pro, 2019.4.x LTS at this moment at my work now, we have 4 programs in preproduction stage, and 3 are in development now, all are WebGL, generally, everything works fine.

    But unfortunatly I cannot tell you just anything about builds with custom threads usage, cause I cannot make them work at all yet. We used Tasks and Synchronization contexts in our standalone builds, but we did not try them in wasm at all, cause we thought threading "settings" are disabled in different browsers for webassembly (I think cause of Spectre security vulnerability)

    I am experimenting with my pet projects at this moment, but I have no success with threading yet.

    2020.1.2 Build fails, my 2020.1.0 Build shows error at startup

    errorthreadsenabled.PNG

    All I can say: async methods work fine, Unity Job System shedules jobs and works fine too, and its great! UniTasks can be used to await Unity Job System JobHandle for example.

    var cutterJobHandle = cutterJob.Schedule();
    await UniTask.WaitUntil(() => cutterJobHandle.IsCompleted);

    These things work fine.
    But I cant use UniTask.Run(), cause enabling threads breaks my builds now.
    In other cases WebGL are very stable.

    I hope my answer was something useful)
     
  50. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    154
    I see they are working hard, and we have 2020.1 with new loader, project Tiny, and threading from 2019.1. These are all good things for us.