Skip to content
This repository was archived by the owner on Jul 11, 2025. It is now read-only.
This repository was archived by the owner on Jul 11, 2025. It is now read-only.

Duality using a different SynchronizationContext inside the editor #592

@Rick-van-Dam

Description

@Rick-van-Dam

Summary

Currently inside the editor duality uses the WindowsFormsSynchronizationContext. However outside the editor it uses no SynchronizationContext (which means this context is either null or equal to SynchronizationContext. This can cause code to behave in a different way when running outside the editor and most likely it will break if this is the case.

To fix this inconsistency the following solutions could be applied:

  1. Make sure that duality uses no SynchronizationContext inside the editor. However since winforms depends on this this will probably mean you need to run winforms and duality in separate threads. I suspect many things will break if this is done.
  2. Make a custom DualitySynchronizationContext that will invoke the continuations in the OnUpdate loop. When using await this will make Tasks have the same behavior as my PathRequest class in Pathfindax meaning continuations will execute on the mainthread. Make sure this context is only applied outside the editor as it will probably break winforms.
  3. Document this is a difference between running inside the editor and outside.

How to reproduce

  • Create a new component and implement ICmpInitializable
  • Put the following code in the OnInit method (the following code could also be done with await syntax):
Log.Game.Write($"Init thread: {Thread.CurrentThread.ManagedThreadId} Context: {SynchronizationContext.Current}");
Task.Run(() =>
{
    Log.Game.Write($"Task run Thread: {Thread.CurrentThread.ManagedThreadId}");
}).ContinueWith(x =>
{
    Log.Game.Write($"Task run continuation Thread: {Thread.CurrentThread.ManagedThreadId}");
}, TaskScheduler.FromCurrentSynchronizationContext());
  • Run this code from inside the editor and from visual studio. Note that inside the editor the continuation is on the mainthread but in visual studio its on a different thread (a threadpool thread to be precise).

Workaround

  • While possible it can be quite alot of work to workaround this. In pathfindax I made a custom awaitable with its own custom logic so that the continuation is synced to the mainthread thus avoiding this whole issue. It stores the continuation in a callback which is then called in the OnBeforeUpdate of the plugin.

Analysis

If going for 1:

  • Duality wil run isolated from any UI no matter if its inside an editor or not.
  • Likely very complex to implement requiring many changes.

If going for 2:

  • Proper support for Tasks as the continuation will execute on the mainthread. Basically the same behavior when running a winforms or WPF application.
  • Still different SynchronizationContext inside the editor vs outside. However the behavior for the enduser 'should' be the same.

If going for 3:

  • Basically saying duality does not properly support Tasks as it can lead to inconsistent behavior.
  • Easy to implement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CoreArea: Duality runtime or launcherEditorArea: Duality editor or support librariesTaskToDo that's neither a Bug, nor a Feature

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions