diff --git a/src/System.Windows.Forms.Analyzers/src/System/Windows/Forms/Analyzers/Diagnostics/DiagnosticIDs.cs b/src/System.Windows.Forms.Analyzers/src/System/Windows/Forms/Analyzers/Diagnostics/DiagnosticIDs.cs index 32ccd39f5cb..c57f90e29ad 100644 --- a/src/System.Windows.Forms.Analyzers/src/System/Windows/Forms/Analyzers/Diagnostics/DiagnosticIDs.cs +++ b/src/System.Windows.Forms.Analyzers/src/System/Windows/Forms/Analyzers/Diagnostics/DiagnosticIDs.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms.Analyzers.Diagnostics; internal static class DiagnosticIDs { - public const string UrlFormat = "https://aka.ms/winforms-experimental/{0}"; + public const string UrlFormat = "https://aka.ms/winforms-warnings/{0}"; // Application Configuration, number group 0001+ public const string UnsupportedProjectType = "WFO0001"; diff --git a/src/System.Windows.Forms/src/GlobalSuppressions.cs b/src/System.Windows.Forms/src/GlobalSuppressions.cs index cbacdc46a5f..30dc6b18e0e 100644 --- a/src/System.Windows.Forms/src/GlobalSuppressions.cs +++ b/src/System.Windows.Forms/src/GlobalSuppressions.cs @@ -260,3 +260,10 @@ [assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.Forms.BindingManagerBase.onPositionChangedHandler")] [assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.Forms.CurrencyManager.listposition")] [assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.Forms.CurrencyManager.finalType")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.Control.InvokeAsync``1(System.Func{``0},System.Threading.CancellationToken)~System.Threading.Tasks.Task{``0}")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.Control.InvokeAsync(System.Func{System.Threading.CancellationToken,System.Threading.Tasks.ValueTask},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.Control.InvokeAsync``1(System.Func{System.Threading.CancellationToken,System.Threading.Tasks.ValueTask{``0}},System.Threading.CancellationToken)~System.Threading.Tasks.Task{``0}")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.Control.InvokeAsync(System.Action,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.TaskDialogPage,System.Windows.Forms.TaskDialogStartupLocation)~System.Threading.Tasks.Task{System.Windows.Forms.TaskDialogButton}")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.IWin32Window,System.Windows.Forms.TaskDialogPage,System.Windows.Forms.TaskDialogStartupLocation)~System.Threading.Tasks.Task{System.Windows.Forms.TaskDialogButton}")] +[assembly: SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Analyzer wrongly complains for new APIs - known issue.", Scope = "member", Target = "~M:System.Windows.Forms.TaskDialog.ShowDialogAsync(System.IntPtr,System.Windows.Forms.TaskDialogPage,System.Windows.Forms.TaskDialogStartupLocation)~System.Threading.Tasks.Task{System.Windows.Forms.TaskDialogButton}")] diff --git a/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt b/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt index 085a354e97f..9923ae55cb6 100644 --- a/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt +++ b/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt @@ -1,7 +1,6 @@ -static System.Windows.Forms.TaskDialog.ShowDialogAsync(nint hwndOwner, System.Windows.Forms.TaskDialogPage! page) -> System.Threading.Tasks.Task! -static System.Windows.Forms.TaskDialog.ShowDialogAsync(nint hwndOwner, System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation) -> System.Threading.Tasks.Task! -static System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.TaskDialogPage! page) -> System.Threading.Tasks.Task! -static System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation) -> System.Threading.Tasks.Task! +static System.Windows.Forms.TaskDialog.ShowDialogAsync(nint hwndOwner, System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation = System.Windows.Forms.TaskDialogStartupLocation.CenterOwner) -> System.Threading.Tasks.Task! +static System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.IWin32Window! owner, System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation = System.Windows.Forms.TaskDialogStartupLocation.CenterOwner) -> System.Threading.Tasks.Task! +static System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation = System.Windows.Forms.TaskDialogStartupLocation.CenterScreen) -> System.Threading.Tasks.Task! System.Windows.Forms.Control.InvokeAsync(System.Action! callback, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! System.Windows.Forms.Control.InvokeAsync(System.Func! callback, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! System.Windows.Forms.Control.InvokeAsync(System.Func>! callback, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Control_InvokeAsync.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Control_InvokeAsync.cs index 3ed1189ab56..cedced54dba 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Control_InvokeAsync.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Control_InvokeAsync.cs @@ -27,9 +27,7 @@ public partial class Control /// . /// /// -#pragma warning disable RS0026 // API with optional parameter(s) should have the most parameters amongst its public overloads public async Task InvokeAsync(Action callback, CancellationToken cancellationToken = default) -#pragma warning restore RS0026 // API with optional parameter(s) should have the most parameters amongst its public overloads { ArgumentNullException.ThrowIfNull(callback); @@ -38,12 +36,12 @@ public async Task InvokeAsync(Action callback, CancellationToken cancellationTok return; } - TaskCompletionSource tcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + TaskCompletionSource completion = new(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register(() => tcs.SetCanceled(), useSynchronizationContext: false)) + using (cancellationToken.Register(() => completion.SetCanceled(), useSynchronizationContext: false)) { BeginInvoke(WrappedAction); - await tcs.Task.ConfigureAwait(false); + await completion.Task.ConfigureAwait(false); } void WrappedAction() @@ -52,16 +50,16 @@ void WrappedAction() { if (cancellationToken.IsCancellationRequested) { - tcs.SetCanceled(cancellationToken); + completion.SetCanceled(cancellationToken); return; } callback(); - tcs.TrySetResult(); + completion.TrySetResult(); } catch (Exception ex) { - tcs.TrySetException(ex); + completion.TrySetException(ex); } } } @@ -95,9 +93,7 @@ void WrappedAction() /// . /// /// -#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters public async Task InvokeAsync(Func callback, CancellationToken cancellationToken = default) -#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters { ArgumentNullException.ThrowIfNull(callback); @@ -106,12 +102,12 @@ public async Task InvokeAsync(Func callback, CancellationToken cancella return default!; } - TaskCompletionSource tcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + TaskCompletionSource completion = new(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register(() => tcs.SetCanceled(), useSynchronizationContext: false)) + using (cancellationToken.Register(() => completion.SetCanceled(), useSynchronizationContext: false)) { BeginInvoke(WrappedCallback); - return await tcs.Task.ConfigureAwait(false); + return await completion.Task.ConfigureAwait(false); } void WrappedCallback() @@ -120,16 +116,16 @@ void WrappedCallback() { if (cancellationToken.IsCancellationRequested) { - tcs.TrySetCanceled(cancellationToken); + completion.TrySetCanceled(cancellationToken); return; } T result = callback(); - tcs.TrySetResult(result); + completion.TrySetResult(result); } catch (Exception ex) { - tcs.TrySetException(ex); + completion.TrySetException(ex); } } } @@ -162,9 +158,7 @@ void WrappedCallback() /// . /// /// -#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters public async Task InvokeAsync(Func callback, CancellationToken cancellationToken = default) -#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters { ArgumentNullException.ThrowIfNull(callback); @@ -173,12 +167,12 @@ public async Task InvokeAsync(Func callback, Cance return; } - TaskCompletionSource tcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + TaskCompletionSource completion = new(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register(() => tcs.SetCanceled(), useSynchronizationContext: false)) + using (cancellationToken.Register(() => completion.SetCanceled(), useSynchronizationContext: false)) { BeginInvoke(async () => await WrappedCallbackAsync().ConfigureAwait(false)); - await tcs.Task.ConfigureAwait(false); + await completion.Task.ConfigureAwait(false); } async Task WrappedCallbackAsync() @@ -187,16 +181,16 @@ async Task WrappedCallbackAsync() { if (cancellationToken.IsCancellationRequested) { - tcs.TrySetCanceled(cancellationToken); + completion.TrySetCanceled(cancellationToken); return; } await callback(cancellationToken).ConfigureAwait(false); - tcs.TrySetResult(); + completion.TrySetResult(); } catch (Exception ex) { - tcs.TrySetException(ex); + completion.TrySetException(ex); } } } @@ -228,9 +222,7 @@ async Task WrappedCallbackAsync() /// . /// /// -#pragma warning disable RS0026 // API with optional parameter(s) should have the most parameters amongst its public overloads public async Task InvokeAsync(Func> callback, CancellationToken cancellationToken = default) -#pragma warning restore RS0026 // API with optional parameter(s) should have the most parameters amongst its public overloads { ArgumentNullException.ThrowIfNull(callback); @@ -239,12 +231,12 @@ public async Task InvokeAsync(Func> callba return default!; } - TaskCompletionSource tcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + TaskCompletionSource completion = new(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register(() => tcs.SetCanceled(), useSynchronizationContext: false)) + using (cancellationToken.Register(() => completion.SetCanceled(), useSynchronizationContext: false)) { BeginInvoke(async () => await WrappedCallbackAsync().ConfigureAwait(false)); - return await tcs.Task.ConfigureAwait(false); + return await completion.Task.ConfigureAwait(false); } async Task WrappedCallbackAsync() @@ -252,11 +244,11 @@ async Task WrappedCallbackAsync() try { var returnValue = await callback(cancellationToken).ConfigureAwait(false); - tcs.TrySetResult(returnValue); + completion.TrySetResult(returnValue); } catch (Exception ex) { - tcs.TrySetException(ex); + completion.TrySetException(ex); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Dialogs/TaskDialog/TaskDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Dialogs/TaskDialog/TaskDialog.cs index bc80ce14ca2..eab6a1fbfc1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Dialogs/TaskDialog/TaskDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Dialogs/TaskDialog/TaskDialog.cs @@ -304,35 +304,8 @@ private static TaskDialogButton CreatePlaceholderButton(TaskDialogResult result) /// /// The page instance that contains the contents which this task dialog will display. /// - /// - /// - /// Showing the dialog will bind the and its controls until - /// this method returns or the dialog is navigated to a different page. - /// - /// - /// - /// The which was clicked by the user to close the dialog. - /// - /// - /// is . - /// - /// - /// The specified contains an invalid configuration. - /// - [Experimental(DiagnosticIDs.ExperimentalAsync, UrlFormat = DiagnosticIDs.UrlFormat)] - public static Task ShowDialogAsync( - TaskDialogPage page) - => ShowDialogAsync(IntPtr.Zero, page.OrThrowIfNull(), TaskDialogStartupLocation.CenterOwner); - - /// - /// Shows the task dialog with the specified owner asynchronously. - /// - /// - /// The page instance that contains the contents which this task dialog will display. - /// - /// - /// The handle of the owner window, or to show a - /// modeless dialog. + /// + /// Gets or sets the position of the task dialog when it is shown. /// /// /// @@ -351,9 +324,9 @@ public static Task ShowDialogAsync( /// [Experimental(DiagnosticIDs.ExperimentalAsync, UrlFormat = DiagnosticIDs.UrlFormat)] public static Task ShowDialogAsync( - IntPtr hwndOwner, - TaskDialogPage page) - => ShowDialogAsync(IntPtr.Zero, page.OrThrowIfNull(), TaskDialogStartupLocation.CenterOwner); + TaskDialogPage page, + TaskDialogStartupLocation startupLocation = TaskDialogStartupLocation.CenterScreen) + => ShowDialogAsync(IntPtr.Zero, page.OrThrowIfNull(), startupLocation); /// /// Shows the task dialog with the specified owner asynchronously. @@ -361,6 +334,9 @@ public static Task ShowDialogAsync( /// /// The page instance that contains the contents which this task dialog will display. /// + /// + /// The owner window. + /// /// /// Gets or sets the position of the task dialog when it is shown. /// @@ -381,9 +357,10 @@ public static Task ShowDialogAsync( /// [Experimental(DiagnosticIDs.ExperimentalAsync, UrlFormat = DiagnosticIDs.UrlFormat)] public static Task ShowDialogAsync( + IWin32Window owner, TaskDialogPage page, - TaskDialogStartupLocation startupLocation) - => ShowDialogAsync(IntPtr.Zero, page.OrThrowIfNull(), startupLocation); + TaskDialogStartupLocation startupLocation = TaskDialogStartupLocation.CenterOwner) => + ShowDialogAsync(owner.Handle, page, startupLocation); /// /// Shows the task dialog with the specified owner asynchronously. @@ -392,8 +369,7 @@ public static Task ShowDialogAsync( /// The page instance that contains the contents which this task dialog will display. /// /// - /// The handle of the owner window, or to show a - /// modeless dialog. + /// The handle of the owner window, or to show a modeless dialog. /// /// /// Gets or sets the position of the task dialog when it is shown. @@ -413,14 +389,15 @@ public static Task ShowDialogAsync( /// /// The specified contains an invalid configuration. /// + [Experimental(DiagnosticIDs.ExperimentalAsync, UrlFormat = DiagnosticIDs.UrlFormat)] public static async Task ShowDialogAsync( - IntPtr hwndOwner, + nint hwndOwner, TaskDialogPage page, - TaskDialogStartupLocation startupLocation) + TaskDialogStartupLocation startupLocation = TaskDialogStartupLocation.CenterOwner) { ArgumentNullException.ThrowIfNull(page); - var tcs = new TaskCompletionSource(); + var completion = new TaskCompletionSource(); TaskDialog? dialog = null; @@ -436,7 +413,7 @@ public static async Task ShowDialogAsync( TaskDialogButton result; - result = await tcs.Task.ConfigureAwait(true); + result = await completion.Task.ConfigureAwait(true); return result; void ShowDialogProc() @@ -444,11 +421,11 @@ void ShowDialogProc() try { dialog = new(); - tcs.TrySetResult(dialog.ShowDialogInternal(hwndOwner, page, startupLocation)); + completion.TrySetResult(dialog.ShowDialogInternal(hwndOwner, page, startupLocation)); } catch (Exception ex) { - tcs.TrySetException(ex); + completion.TrySetException(ex); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs index 97110a7017e..1c609b267c3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs @@ -161,9 +161,9 @@ public partial class Form : ContainerControl private bool _processingDpiChanged; private bool _inRecreateHandle; - private TaskCompletionSource? _tcsNonModalForm; - private TaskCompletionSource? _tcsModalForm; - private readonly Lock _syncObj = new(); + private TaskCompletionSource? _nonModalFormCompletion; + private TaskCompletionSource? _modalFormCompletion; + private readonly Lock _lock = new(); /// /// Initializes a new instance of the class. @@ -3355,7 +3355,7 @@ protected override void Dispose(bool disposing) PInvoke.DestroyMenu(dummyMenu); } - _tcsNonModalForm?.TrySetResult(); + _nonModalFormCompletion?.TrySetResult(); } else { @@ -3861,13 +3861,13 @@ protected virtual void OnFormClosed(FormClosedEventArgs e) ((FormClosedEventHandler?)Events[s_formClosedEvent])?.Invoke(this, e); // This effectively ends an `await form.ShowAsync();` call. - _tcsNonModalForm?.TrySetResult(); + _nonModalFormCompletion?.TrySetResult(); } catch (Exception ex) { - if (_tcsNonModalForm is not null) + if (_nonModalFormCompletion is not null) { - _tcsNonModalForm.TrySetException(ex); + _nonModalFormCompletion.TrySetException(ex); } else { @@ -5321,14 +5321,14 @@ public async Task ShowAsync(IWin32Window? owner = null) { // We lock the access to the task completion source to prevent // multiple calls to ShowAsync from interfering with each other. - lock (_syncObj) + lock (_lock) { - if (_tcsNonModalForm is not null || _tcsModalForm is not null) + if (_nonModalFormCompletion is not null || _modalFormCompletion is not null) { throw new InvalidOperationException(SR.Form_HasAlreadyBeenShownAsync); } - _tcsNonModalForm = new(TaskCreationOptions.RunContinuationsAsynchronously); + _nonModalFormCompletion = new(TaskCreationOptions.RunContinuationsAsynchronously); } if (SynchronizationContext.Current is null) @@ -5344,7 +5344,7 @@ public async Task ShowAsync(IWin32Window? owner = null) // Wait until the form is closed or disposed. try { - await _tcsNonModalForm.Task.ConfigureAwait(true); + await _nonModalFormCompletion.Task.ConfigureAwait(true); } catch (Exception ex) { @@ -5353,7 +5353,7 @@ public async Task ShowAsync(IWin32Window? owner = null) } finally { - _tcsNonModalForm = null; + _nonModalFormCompletion = null; } void ShowFormInternally(IWin32Window? owner) @@ -5365,23 +5365,23 @@ void ShowFormInternally(IWin32Window? owner) } catch (Exception ex) { - _tcsNonModalForm.TrySetException(ex); + _nonModalFormCompletion.TrySetException(ex); } } } private protected override bool SuppressApplicationOnThreadException(Exception ex) { - lock (_syncObj) + lock (_lock) { - if (_tcsNonModalForm is not null) + if (_nonModalFormCompletion is not TaskCompletionSource completion) { - _tcsNonModalForm.TrySetException(ex); - return true; + return false; } - } - return false; + completion.TrySetException(ex); + return true; + } } /// @@ -5621,14 +5621,14 @@ public DialogResult ShowDialog(IWin32Window? owner) private Task ShowDialogAsyncInternal(IWin32Window? owner) { - lock (_syncObj) + lock (_lock) { - if (_tcsNonModalForm is not null || _tcsModalForm is not null) + if (_nonModalFormCompletion is not null || _modalFormCompletion is not null) { throw new InvalidOperationException(SR.Form_HasAlreadyBeenShownAsync); } - _tcsModalForm = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + _modalFormCompletion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); } if (SynchronizationContext.Current is null) @@ -5640,10 +5640,10 @@ private Task ShowDialogAsyncInternal(IWin32Window? owner) ?? throw new InvalidOperationException(SR.FormOrTaskDialog_NoSyncContextForShowAsync); syncContext.Post((state) => ShowDialogProc( - tcsModalForm: ref _tcsModalForm, owner: owner), + tcsModalForm: ref _modalFormCompletion, owner: owner), state: null); - return _tcsModalForm.Task; + return _modalFormCompletion.Task; void ShowDialogProc(ref TaskCompletionSource tcsModalForm, IWin32Window? owner = default) {