tryphotino / photino.NET

https://tryphotino.io
Apache License 2.0
884 stars 73 forks source link

Open PhotinoWindow from thread other than main #154

Closed philippjbauer closed 10 months ago

philippjbauer commented 10 months ago

Additional PhotinoWindow instances can't be created from a detached event thread.

On macOS and Linux it is enough to set the _manageThreadId of the new window to the parent's managed thread ID instead of the Environment.CurrentManagedThreadId:

public PhotinoWindow(PhotinoWindow parent = null)
{
        _dotNetParent = parent;
        _managedThreadId = parent is null
            ? Environment.CurrentManagedThreadId
            : parent.ManagedThreadId;
        // ...
}

On Windows it crashes with the following message:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
   at PhotinoNET.PhotinoWindow.Photino_Invoke(IntPtr, PhotinoNET.InvokeCallback)
--------------------------------
   at PhotinoNET.PhotinoWindow.Invoke(System.Action)
   at PhotinoNET.PhotinoWindow.WaitForClose()
   at CODE.Transcriber.OpenConfigurationActionHandler+<HandleAsync>d__4.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon ByRef)
   at CODE.Transcriber.OpenConfigurationActionHandler.HandleAsync(CODE.Transcriber.OpenConfigurationActionRequest)
   at CODE.Transcriber.ActionHandler`1+<InvokeAsync>d__6[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon ByRef)
   at CODE.Transcriber.ActionHandler`1[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].InvokeAsync(System.String)
   at System.RuntimeMethodHandle.InvokeMethod(System.Object, Void**, System.Signature, Boolean)
   at System.Reflection.MethodInvoker.Invoke(System.Object, IntPtr*, System.Reflection.BindingFlags)
   at System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
   at CODE.Transcriber.ActionRouter+<>c__DisplayClass5_0.<InvokeRequestHandler>b__0()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread)
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()

We need to check if there is some way to create new windows from the main thread in some unified way across all operating systems.

philippjbauer commented 10 months ago

The behavior without the change above is just an unresponsive window with subsequent crash of the window. The main window remains open though.

Screenshot 2023-11-13 at 2 11 34 PM
philippjbauer commented 10 months ago

Ended up being another issue in the application.