diff --git a/docs/PC004.md b/docs/PC004.md new file mode 100644 index 0000000..3aba2cd --- /dev/null +++ b/docs/PC004.md @@ -0,0 +1,41 @@ +# PC004: Delegate.BeginInvoke and EndInvoke are Unsupported on .NET Core + +## Cause + +You're using the [Asynchronous Programming Model](https://docs.microsoft.com/dotnet/standard/asynchronous-programming-patterns/calling-synchronous-methods-asynchronously) to invoke a delegate (via the `BeginInvoke` method) which is unsupported on .NET Core. + +## Rule description + +The `BeginInvoke` and `EndInvoke` methods automatically generated for delegate types at compile-time are not supported by .NET Core. Calling these methods will throw a `NotSupportedException`. Task-based [TPL](https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl) patterns should be used instead. + +## How to fix violations + +Remove calls to `BeginInvoke` and `EndInvoke`. Replace `IAsyncResult` usage with `Task`-based patterns, instead. For example: + +```CSharp +delegate int WorkDelegate(int arg); +... +WorkDelegate del = DoWork; + +// Schedule the work using a Task +Console.WriteLine("Starting with Task.Run"); +var workTask = Task.Run(() => DoWork(11)); + +// Optionally, we can specify a continuation delegate +// to execute when DoWork has finished +var followUpTask = workTask.ContinueWith(TaskCallback); + +// This writes output to the console while DoWork is running in the background +Console.WriteLine("Waiting on work..."); + +// We await the task instead of calling EndInvoke +var ret = await workTask; +await folowUpTask; +``` + +## When to suppress warnings + +These methods are never usable on .NET Core. Suppress the warning only if: + +1. These code paths are only used while running on .NET Framework. +2. The analyzer has mistakenly flagged an API that is not a call to a compiler-generated `BeginInvoke`/`EndInvoke` APM method.