Skip to content

Invoke (SendAsyncMethod) is lost when resizing window #39

@marius-klimantavicius

Description

@marius-klimantavicius

Platform: windows (I am using this project as basis for supporting native AOT).

Steps to reproduce:

  1. Create form
  2. Add Load event handler:
Load += (_, _) => {
  ThreadPool.UnsafeQueueUserWorkItem(_ =>
  {
      Thread.Sleep(1000);
      for (var i = 0; i < 100; i++) {
  
          Invoke(() => _label.Text = $"Current: {i}");
          Thread.Sleep(300);
      }
  }, null);
};
  1. Run app
  2. Do resize

Expected result:
_label.Text is continuously updated

Actual result:
_label.Text stops being updated during and after resize

Reason:
This is because Invoke is handled by posting ASYNC_MESSAGE into message loop and expecting the message to be returned by GetMessage/PeekMessage. The issue is that when form is being resized it enters a resize message loop thus our calls to GetMessage/PeekMessage are "bypassed".

Possible fix.
Handle ASYNC_MESSAGE in WndProc instead of XplatUIWin32.GetMessage (this will also require the foster parent to have non-DefWndProc). This is what I have done locally.
Also consider using ASYNC_MESSAGE as a marker and store pending calls in a queue instead of actually sending call info via GCHandle (this is what dotnet/winforms does).

Also possible issue (not sure though): Control.GetInvokableHandle will call CreateHandle if handle does not exist. I am afraid that could cause the handle to be created on a wrong thread if Invoke is called before the control was created. But I don't know if that's a real issue or not I haven't encountered that (haven't tested it either).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions