microsoft / microsoft/WindowsAppSDK

Proposal: Add WinRT APIs to create Windows.System.DispatcherQueueController on current thread easily

Open
#2,466 18 comments 0 reactions 1 assignee View on GitHub

Nobody has claimed this yet.

area-Windowing feature proposal
Dominant language
C++
Stars
4.7k
Forks
471
Avg merge
3d 13h
Merged PRs (30d)
28

Description

I know there is a feature portal for proposal but this is very code-oriented/developer-experience related, so I wrote it here instead of the portal.

## Summary
Now that WinUI 3 mica support is here in 1.1 preview 3, each app that implement mica need to have their own dispatcher queue helper as in the [xaml control gallery](https://github.com/microsoft/WinUI-Gallery/blob/winui3/XamlControlsGallery/ControlPagesSampleCode/SystemBackdrops/SystemBackdropsEnsureSystemDQC.txt#L3), or in this [sample for C++](https://docs.microsoft.com/en-us/windows/apps/windows-app-sdk/system-backdrop-controller).

The ergonomic is not good in C# (dllimport), nor in C++ (using `ABI` namespace and C API directly for a release-defining feature).

This proposal suggests WASDK provide the following WinRT API:
```
namespace Microsoft.Windows.System
{
runtimeclass DispatcherQueueController
{
// Note the return type is WS instead of Microsoft.UI.Dispatching
static Windows.System.DispatcherQueueController CreateOnCurrentThread();
}
}
```
So C# and C++ can all use the same API. In the future this would benefit other supported language projection as well.

On top of that, I'm guessing the existing `Windows::System::DispatcherQueueController::CreateOnDedicatedThread` is just wrapping the ABI interface and C API anyways. To make the API in WinRT complete, this proposal suggests that a complete WinRT API that wraps `IDispatcherQueueController`, `DispatcherQueueOptions`, and `CreateDispatcherQueueController`, as follows:
```
namespace Microsoft::Windows::System
{
enum DispatcherQueueOptions
{
/*Map to existing DispatcherQueueOptions*/
}
runtimeclass DispatcherQueueController
{
static Windows.System.DispatcherQueueController CreateDispatcherQueueController(DispatcherQueueOptions options);
}
}
```

This has the following benefits:
- Improved developer experience
- Remove boilerplate in both languages
- Remove unnecessary errors/efforts on implementing mica
- API consistency (one for dedicated thread, one for current thread)
- Simplify doc effort on mica (I already [submitted a PR](https://github.com/MicrosoftDocs/windows-uwp/pull/3811) fixing C++'s sample code related to dispatcher queue controller)

## Examples Of Proposed API In The Mica Sample
### C++
```diff
winrt::WS::DispatcherQueueController CreateSystemDispatcherQueueController()
{
- DispatcherQueueOptions options
- {
- sizeof(DispatcherQueueOptions),
- DQTYPE_THREAD_CURRENT,
- DQTAT_COM_NONE
- };
-
- ::ABI::Windows::System::IDispatcherQueueController* ptr{ nullptr };
- winrt::check_hresult(CreateDispatcherQueueController(options, &ptr));
- return { ptr, take_ownership_from_abi };
+ return Microsoft::Windows::System::DispatcherQueueController::CreateOnCurrentThread();
}
```
### C#
```diff
class WindowsSystemDispatcherQueueHelper
{
- [StructLayout(LayoutKind.Sequential)]
- struct DispatcherQueueOptions
- {
- internal int dwSize;
- internal int threadType;
- internal int apartmentType;
- }
-
- [DllImport("CoreMessaging.dll")]
- private static extern int CreateDispatcherQueueController([In] DispatcherQueueOptions options, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController);
-
object m_dispatcherQueueController = null;
public void EnsureWindowsSystemDispatcherQueueController()
{
if (Windows.System.DispatcherQueue.GetForCurrentThread() != null)
{
// one already exists, so we'll just use it.
return;
}

- if (m_dispatcherQueueController == null)
- {
- DispatcherQueueOptions options;
- options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
- options.threadType = 2; // DQTYPE_THREAD_CURRENT
- options.apartmentType = 2; // DQTAT_COM_STA
-
- CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
- }
+ m_dispatcherQueueController = Microsoft.Windows.System.DispatcherQueueController.CreateOnCurrentThread();
}
}
```
## Scope
| Capability | Priority |
| :---------- | :------- |
| This proposal will allow supported languages to use (the same) WinRT API to create `Windows::System::DispatcherQueueController` on current thread in 1 line | Must |
| This proposal will allow supported languages to use WinRT API to create `Windows::System::DispatcherQueueController` with options | Must |

## Notes
1. IMO this should be implemented by 1.1. So when this feature is officially rolled out no one has to write `dllimport`/`::ABI::` just to use mica.
2. Note that [the "existing" one in WinUI 3](https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.dispatching.dispatcherqueuecontroller.createoncurrentthread?view=winui-3.0#microsoft-ui-dispatching-dispatcherqueuecontroller-createoncurrentthread) doesn't work as it creates `MUD` instead of `WS` dispatcher queue controller.
3. I'd love to submit a PR for this but I need to make sure the proposal is accepted before investing my time on it.

## Potential Confusion
Developers might be confused about the difference between `Windows::System::DispatcherQueueController`, `Microsoft::Windows::System::DispatcherQueueController` (proposed, only contain static method to create `WS::DispatcherQueueController`), and `Microsoft::UI::Dispatching::DispatcherQueueController`, and which to use. We might need to provide a doc that explains them briefly. The doc might need to explain
- Should use MUDD mostly in WinUI 3
- WSD is the type for e.g. using mica
- MWSD is for convenience method

## Open question
Since the proposed class only contains static methods, is it more appropriate to name it `DispatcherQueueControllerHelper`?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.