PHP & System.Threading.Tasks.Task¶
Imagine having all the C#/.NET objects readily available in your PHP code, including the entire .NET runtime. In this article, we'll take a glance at .NET threading, Tasks, and CLR debugging.
System.Threading.Tasks.Task¶
A task is an object that encapsulates a delegate
, its state and the state of the task itself. Its delegate
is invoked in a "context". The C# language allows for all sorts of whacky things with tasks, such as scheduling them in various contexts, awaiting them asynchronously, and so on.
We won't be doing that in PHP code. We'll "only" create a Task
and we'll run it on a background thread while the main thread will continue executing its code.
The Code¶
We're writing a standard .php
file (i.e. main.php
) with the following valid PHP code:
<?php
use System\Threading\Tasks\Task;
use System\Threading\CancellationToken;
use System\Threading\CancellationTokenSource;
First, we introduce some class aliases, so we can then just write short names in our code. Notice there is no difference between a PHP class or .NET class. It's all the same to the compiler.
Put our code into a global function main
(the name does not matter). The reason is that the compiler works better with local variables - their types can be inferred better and the compiled code is much more efficient.
Now create a CancellationTokenSource
object - we'll use it to cancel the background task, as we usually do in C# programs.
This is where the magic happens; the line above creates a Task
object with a delegate that will be executed on a thread pool, and runs it.
Under the hood, this PHP anonymous function is compiled as a static CLR method with the following signature:
The PeachPie runtime creates a Closure
object, which wraps the delegate to this method together with the use
$token
argument. Then, the PeachPie runtime builds an in-memory Action
delegate which calls the created Closure
. Finally, the Task::Run(Action, CancellationToken)
static method gets invoked.
Inside the anonymous function ({ ... }
) running on a background thread we can do whatever we want to. For exmaple, we can run some computation and periodically check the $token
for cancellation.
After the task is created, we continue the execution on the main thread. In this sample, we schedule the CancellationTokenSource
to cancel after 1 second, and wait synchronously for the background Task
$task
to finish.
Disclaimer¶
Some of the features necessary for this code to run - like passing a struct CancellationToken
between closures, calling methods on value types, or better overload resolution - were implemented in the pre-release version of PeachPie 1.2.0-r17766
. You'll need to grab PeachPie from the sources or get access to our private NuGet feed with all the SDKs, Runtime, and Compiler prepared for you. To get access to the private feed, nightly and release builds, a private forum and premium content, you need to become a Patron.
Building Code¶
As for any other C#/.NET project to run, we need a project file and the dotnet
SDK.
Make sure you have dotnet
(at least 8.0): https://dotnet.microsoft.com/en-us/download
Add the following project file (i.e. system-threading-tasks.msbuildproj
):
<Project Sdk="Peachpie.NET.Sdk/1.2.0-r17797">
<PropertyGroup>
<OutputType>exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<StartupObject>main.php</StartupObject>
</PropertyGroup>
<ItemGroup>
<Compile Include="**/*.php" />
</ItemGroup>
</Project>
The project file is a standard MSBuild project that specifies
-
Peachpie.NET.Sdk
as its "base" project. It defines how to call the compiler, it embeds the compiler binaries themselves, and it defines the default compilation options.dotnet
will get it from the NuGet feed. -
<OutputType>exe</OutputType>
tells the compiler we're building an executable console app. -
<TargetFramework>net8.0</TargetFramework>
is our target ramework, in this case .NET 8.0. -
<Compile Include="**/*.php" />
selects all.php
files in project folder as source files. They will be compiled into the resulting .NET assembly.
Once you have the project file (.msbuildproj
) and source file(s) (.php
), run the build:
and/or run the program:
Project¶
The complete project can be found at https://github.com/iolevel/peachpie-samples/tree/patreon/system-threading-tasks
You can open it in Visual Studio Code, Visual Studio (at least 2022), or Rider. In those IDE's you can click on Run/Debug
and even place breakpoints and debug the code in CLR style.