THRIFT-5902 Add net10 support
Client: netstd
Patch: Jens Geyer
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 186962a..0a0b817 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -304,6 +304,9 @@
     runs-on: ubuntu-24.04
     strategy:
       fail-fast: false
+    defaults:
+      run:
+        shell: bash  # required by net install script
     steps:
       - uses: actions/checkout@v5
 
@@ -313,12 +316,33 @@
           sudo apt-get install -y --no-install-recommends $BUILD_DEPS
           sudo apt-get install -y --no-install-recommends curl openssl ca-certificates
 
-#      the sdk is installed by default, but keep this step for reference
-#      caveat: net9 is (currently?) NOT installed, so manually again
-      - name: Set up .NET SDK
+# This whole setup is getting worse: https://github.com/dotnet/core/discussions/9258
+      - name: Set up .NET SDK (via install script)
         run: |
-          sudo add-apt-repository -y ppa:dotnet/backports
-          sudo apt-get install -y --no-install-recommends dotnet-sdk-9.0
+          # remove any existing install
+          sudo apt remove dotnet*    
+          # install key
+          sudo apt install gpg
+          wget https://dot.net/v1/dotnet-install.asc
+          gpg --import dotnet-install.asc          
+          # download and verify
+          wget https://dot.net/v1/dotnet-install.sh
+          wget https://dot.net/v1/dotnet-install.sig
+          gpg --verify dotnet-install.sig dotnet-install.sh          
+          # run install script
+          chmod +x dotnet-install.sh
+          ./dotnet-install.sh --channel 10.0          
+          # export env vars
+          export DOTNET_ROOT=$HOME/.dotnet
+          export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools          
+          dotnet --list-sdks
+
+#      the sdk is installed by default, but keep this step for reference
+#      especially newer versions are NOT always pre-installed, so manually again
+#      - name: Set up .NET SDK
+#        run: |
+#          sudo add-apt-repository -y ppa:dotnet/backports
+#          sudo apt-get install -y --no-install-recommends dotnet-sdk-10.0
 #      end
 
       - name: Run bootstrap
diff --git a/build/docker/ubuntu-focal/Dockerfile b/build/docker/ubuntu-focal/Dockerfile
index e0244fc..18234bf 100644
--- a/build/docker/ubuntu-focal/Dockerfile
+++ b/build/docker/ubuntu-focal/Dockerfile
@@ -137,7 +137,7 @@
       dart=$DART_VERSION
 ENV PATH /usr/lib/dart/bin:$PATH
 
-# Because Ubuntu 20.04 reaches end of life in April [actually May] 2025, Microsoft has decided not to support .NET 9 on Ubuntu 20.04.
+# Because Ubuntu 20.04 turned EOL in April/May 2025, Microsoft does not support .NET 9 or higher on that platform
 RUN apt-get install -y --no-install-recommends \
       `# dotnet core dependencies` \
       dotnet-sdk-8.0 \
diff --git a/build/docker/ubuntu-jammy/Dockerfile b/build/docker/ubuntu-jammy/Dockerfile
index 8f66a56..5e83948 100644
--- a/build/docker/ubuntu-jammy/Dockerfile
+++ b/build/docker/ubuntu-jammy/Dockerfile
@@ -133,10 +133,10 @@
 RUN add-apt-repository ppa:dotnet/backports
 RUN apt-get install -y --no-install-recommends \
   `# dotnet core dependencies` \
-  dotnet-sdk-9.0 \
-  dotnet-runtime-9.0 \
-  aspnetcore-runtime-9.0 \
-  dotnet-apphost-pack-9.0
+  dotnet-sdk-10.0 \
+  dotnet-runtime-10.0 \
+  aspnetcore-runtime-10.0 \
+  dotnet-apphost-pack-10.0
 
 # Erlang dependencies
 ARG ERLANG_OTP_VERSION=25.3.2.9
diff --git a/build/docker/ubuntu-noble/Dockerfile b/build/docker/ubuntu-noble/Dockerfile
index 374b4b5..86617e0 100644
--- a/build/docker/ubuntu-noble/Dockerfile
+++ b/build/docker/ubuntu-noble/Dockerfile
@@ -132,10 +132,10 @@
 RUN add-apt-repository ppa:dotnet/backports
 RUN apt-get install -y --no-install-recommends \
   `# dotnet core dependencies` \
-  dotnet-sdk-9.0 \
-  dotnet-runtime-9.0 \
-  aspnetcore-runtime-9.0 \
-  dotnet-apphost-pack-9.0
+  dotnet-sdk-10.0 \
+  dotnet-runtime-10.0 \
+  aspnetcore-runtime-10.0 \
+  dotnet-apphost-pack-10.0
 
 # Erlang dependencies
 ARG ERLANG_OTP_VERSION=25.3.2.9
diff --git a/build/veralign.sh b/build/veralign.sh
index b929f1f..3967d84 100755
--- a/build/veralign.sh
+++ b/build/veralign.sh
@@ -74,6 +74,7 @@
 FILES[lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj]=simpleReplace
 FILES[lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net8/Thrift.Compile.net8.csproj]=simpleReplace
 FILES[lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net9/Thrift.Compile.net9.csproj]=simpleReplace
+FILES[lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Thrift.Compile.net10.csproj]=simpleReplace
 FILES[lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.netstd2/Thrift.Compile.netstd2.csproj]=simpleReplace
 FILES[lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj]=simpleReplace
 FILES[lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj]=simpleReplace
diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
index c35ce56..5c67f66 100644
--- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
@@ -82,6 +82,9 @@
         else if (iter->first.compare("no_deepcopy") == 0) {
           suppress_deepcopy = true;
         }
+        else if (iter->first.compare("net10") == 0) {
+          target_net_version = 10;
+        }
         else if (iter->first.compare("net9") == 0) {
           target_net_version = 9;
         }
@@ -202,9 +205,12 @@
 
 void t_netstd_generator::pragmas_and_directives(ostream& out)
 {
-    if( target_net_version >= 9) {
+    if( target_net_version >= 10) {
+        out << "// targeting net 10" << '\n';
+        out << "#if( !NET10_0_OR_GREATER)" << '\n';
+    } else if( target_net_version >= 9) {
         out << "// targeting net 9" << '\n';
-        out << "#if( !NET9_0_OR_GREATER)" << '\n';
+        out << "#if( NET10_0_OR_GREATER || !NET9_0_OR_GREATER)" << '\n';
     } else if( target_net_version >= 8) {
         out << "// targeting net 8" << '\n';
         out << "#if( NET9_0_OR_GREATER || !NET8_0_OR_GREATER)" << '\n';
@@ -2651,7 +2657,7 @@
 
     string tmpvar = tmp("tmp");
     out << indent() << "var " << tmpvar << " = $\"Error occurred in {GetType().FullName}: {" << tmpex << ".Message}\";" << '\n';
-    out << indent() << "if(_logger != null)" << '\n';
+    out << indent() << "if ((_logger != null) && _logger.IsEnabled(LogLevel.Error))" << '\n';
     indent_up();
     out << indent() << "_logger.LogError(\"{Exception}, {Message}\", " << tmpex << ", " << tmpvar << ");" << '\n';
     indent_down();
@@ -4002,6 +4008,7 @@
     "    pascal:          Generate Pascal Case property names according to Microsoft naming convention.\n"
     "    net8:            Enable features that require net8 and C# 12 or higher.\n"
     "    net9:            Enable features that require net9 and C# 13 or higher.\n"
+    "    net10:           Enable features that require net10 and C# 14 or higher.\n"
     "    no_deepcopy:     Suppress generation of " + DEEP_COPY_METHOD_NAME + "() method.\n"
     "    async_postfix:   Append \"Async\" to all service methods (maintains compatibility with existing code).\n"
 )
diff --git a/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj b/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj
index e97a62c..9ad2c5b 100644
--- a/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj
+++ b/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj
@@ -20,7 +20,7 @@
   
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <Version>0.23.0</Version>
     <LangVersion>latestMajor</LangVersion>
     <TieredCompilation>false</TieredCompilation>
diff --git a/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Impl/Thrift5253/MyService.cs b/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Impl/Thrift5253/MyService.cs
new file mode 100644
index 0000000..8e13082
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Impl/Thrift5253/MyService.cs
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation(ASF) under one
+// or more contributor license agreements.See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Thrift5253;
+
+namespace Thrift.Compile.net10.Impl.Thrift5253
+{
+    class MyServiceImpl : MyService.IAsync
+    {
+        public Task<AsyncProcessor> AsyncProcessor_(AsyncProcessor? input, CancellationToken cancellationToken = default)
+        {
+            return Task.FromResult(new AsyncProcessor() { Foo = input?.Foo ?? 0 });
+        }
+
+        public Task<BrokenResult> Broken(BrokenArgs? input, CancellationToken cancellationToken = default)
+        {
+            return Task.FromResult(new BrokenResult() { Foo = input?.Foo ?? 0 });
+        }
+
+        public Task<Client> Client_(Client? input, CancellationToken cancellationToken = default)
+        {
+            _ = cancellationToken;
+            return Task.FromResult(new Client() { Foo = input?.Foo ?? 0 });
+        }
+
+        public Task<IAsync> IAsync_(IAsync? input, CancellationToken cancellationToken = default)
+        {
+            return Task.FromResult(new IAsync() { Foo = input?.Foo ?? 0 });
+        }
+
+        public Task<InternalStructs> InternalStructs_(InternalStructs? input, CancellationToken cancellationToken = default)
+        {
+            return Task.FromResult(new InternalStructs() { Foo = input?.Foo ?? 0 });
+        }
+
+        public Task TestAsync(CancellationToken cancellationToken = default)
+        {
+            return Task.CompletedTask;
+        }
+
+        public Task TestXsync(CancellationToken cancellationToken = default)
+        {
+            return Task.CompletedTask;
+        }
+
+        public Task<WorksRslt> Works(WorksArrrgs? input, CancellationToken cancellationToken = default)
+        {
+            return Task.FromResult(new WorksRslt() { Foo = input?.Foo ?? 0 });
+        }
+    }
+}
diff --git a/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Properties/AssemblyInfo.cs b/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5bd3c6f
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Properties/AssemblyInfo.cs
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation(ASF) under one
+// or more contributor license agreements.See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("The Apache Software Foundation")]
+[assembly: AssemblyProduct("Thrift")]
+[assembly: AssemblyCopyright("The Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("1b468b7a-a53b-46de-90da-5f9ad7707ef4")]
\ No newline at end of file
diff --git a/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Thrift.Compile.net10.csproj b/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Thrift.Compile.net10.csproj
new file mode 100644
index 0000000..3f267e7
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.Compile.Tests/Thrift.Compile.net10/Thrift.Compile.net10.csproj
@@ -0,0 +1,89 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <!--
+    Licensed to the Apache Software Foundation(ASF) under one
+    or more contributor license agreements.See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+  	  http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+  -->
+
+  <PropertyGroup>
+    <ThriftVersion>0.23.0</ThriftVersion>
+    <ThriftVersionOutput>Thrift version $(ThriftVersion)</ThriftVersionOutput>
+    <TargetFramework>net10.0</TargetFramework>
+    <LangVersion>latestMajor</LangVersion>
+    <Version>$(ThriftVersion).0</Version>
+    <AssemblyName>Thrift.Compile.net10</AssemblyName>
+    <PackageId>Thrift.Compile.net10</PackageId>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="../../../Thrift/Thrift.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="System.ServiceModel.Primitives" Version="8.1.2" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Update="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
+  </ItemGroup>
+
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <CreateProperty Condition="'$(OS)' == 'Windows_NT'" Value=".exe">
+      <Output TaskParameter="Value" PropertyName="EXECUTABLE_SUFFIX" />
+    </CreateProperty>
+    <!-- Check on the path -->
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true" IgnoreExitCode="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="'$(OS)' != 'Windows_NT'" Command="which thrift" ConsoleToMSBuild="true" IgnoreExitCode="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <!-- Check in the current directory -->
+    <CreateProperty Condition="Exists('thrift$(EXECUTABLE_SUFFIX)')" Value="thrift$(EXECUTABLE_SUFFIX)">
+      <Output TaskParameter="Value" PropertyName="PathToThrift" />
+    </CreateProperty>
+    <!-- Check for the root projects output -->
+    <CreateProperty Condition="Exists('$(ProjectDir)/../../../../../compiler/cpp/thrift$(EXECUTABLE_SUFFIX)')" Value="$(ProjectDir)/../../../../../compiler/cpp/thrift$(EXECUTABLE_SUFFIX)">
+      <Output TaskParameter="Value" PropertyName="PathToThrift" />
+    </CreateProperty>
+    <Error Condition="!Exists('$(PathToThrift)')" Text="Thrift executable could not be found." />
+    <!-- Make sure the thrift version found is the same as the projects version -->
+    <Exec Command="$(PathToThrift) -version" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="ThriftBinaryVersion" />
+    </Exec>
+    <Error Condition="$('$(ThriftBinaryVersion)'::StartsWith('$(ThriftVersionOutput)')) == true" Text="Thrift version returned: '$(ThriftBinaryVersion)' is not equal to the projects version '$(ThriftVersionOutput)'." />
+    <Message Importance="high" Text="Generating tests with thrift binary: '$(PathToThrift)'" />
+    <!-- Generate the thrift test files -->
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../CassandraTest.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../optional_required_default.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../name_conflicts.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../../../../../test/ThriftTest.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../../../../../test/ExceptionStruct.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../../../../../contrib/fb303/if/fb303.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../Thrift5253.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../Thrift5320.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../Thrift5382.thrift" />
+    <Exec Command="$(PathToThrift) -gen netstd:wcf,union,serial,net10 -r ../Thrift5795.thrift" />
+    <!-- special options (see ticket) -->
+    <Exec Command="$(PathToThrift) -gen netstd:net10                  -r ../Thrift5794.thrift" />
+  </Target>
+
+</Project>
diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
index 049c865..96e5076 100644
--- a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
+++ b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <LangVersion>latestMajor</LangVersion>
     <AssemblyName>Thrift.IntegrationTests</AssemblyName>
     <PackageId>Thrift.IntegrationTests</PackageId>
diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj
index 4ad37a3..53acd57 100644
--- a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj
+++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <LangVersion>latestMajor</LangVersion>
     <Version>0.23.0.0</Version>
     <Nullable>enable</Nullable>
@@ -35,7 +35,7 @@
 
   <ItemGroup>
     <ProjectReference Include="..\..\Thrift\Thrift.csproj" />
-    <ProjectReference Include="..\Thrift.Compile.Tests\Thrift.Compile.net9\Thrift.Compile.net9.csproj" />
+    <ProjectReference Include="..\Thrift.Compile.Tests\Thrift.Compile.net10\Thrift.Compile.net10.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/lib/netstd/Thrift.sln b/lib/netstd/Thrift.sln
index feae3fe..fd60dbd 100644
--- a/lib/netstd/Thrift.sln
+++ b/lib/netstd/Thrift.sln
@@ -1,6 +1,6 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.9.34728.123
+# Visual Studio Version 18
+VisualStudioVersion = 18.0.11205.157 d18.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{ED5A45B0-07D1-4507-96B7-83FBD3D031CA}"
 EndProject
@@ -20,6 +20,8 @@
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Compile.net9", "Tests\Thrift.Compile.Tests\Thrift.Compile.net9\Thrift.Compile.net9.csproj", "{967C48D1-1807-41E5-B4BF-DFA6414CC9F2}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.Compile.net10", "Tests\Thrift.Compile.Tests\Thrift.Compile.net10\Thrift.Compile.net10.csproj", "{7899EDD8-1CA5-F033-B68D-D596B20A1941}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -114,6 +116,18 @@
 		{967C48D1-1807-41E5-B4BF-DFA6414CC9F2}.Release|x64.Build.0 = Release|Any CPU
 		{967C48D1-1807-41E5-B4BF-DFA6414CC9F2}.Release|x86.ActiveCfg = Release|Any CPU
 		{967C48D1-1807-41E5-B4BF-DFA6414CC9F2}.Release|x86.Build.0 = Release|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Debug|x64.Build.0 = Debug|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Debug|x86.Build.0 = Debug|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Release|x64.ActiveCfg = Release|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Release|x64.Build.0 = Release|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Release|x86.ActiveCfg = Release|Any CPU
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -125,6 +139,7 @@
 		{58F72FB9-09F5-4D0F-B0B4-36605670BF72} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA}
 		{9A3E11C0-72FD-4DA0-8E61-C7746E751DF7} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA}
 		{967C48D1-1807-41E5-B4BF-DFA6414CC9F2} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA}
+		{7899EDD8-1CA5-F033-B68D-D596B20A1941} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9}
diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj
index 144af49..199c9d5 100644
--- a/lib/netstd/Thrift/Thrift.csproj
+++ b/lib/netstd/Thrift/Thrift.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFrameworks>netstandard2.1;netstandard2.0;net8.0;net9.0</TargetFrameworks>
+    <TargetFrameworks>netstandard2.1;netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>
     <AssemblyName>Thrift</AssemblyName>
     <PackageId>ApacheThrift</PackageId>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
@@ -65,13 +65,6 @@
     <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.6" />
     <PackageReference Include="System.IO.Pipes.AccessControl" Version="5.0.0" Condition="'$(TargetFramework.StartsWith(`netstandard2.`))' == 'true'" />
     <PackageReference Include="System.Net.Http.WinHttpHandler" Version="9.0.6" />
-    <!--
-    <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.0" Condition="'$(TargetFramework.StartsWith(`netstandard2.`))' == 'true'" />
-    <PackageReference Include="System.Net.Requests" Version="4.3.0" Condition="'$(TargetFramework.StartsWith(`netstandard2.`))' == 'true'" />
-    <PackageReference Include="System.Net.NameResolution" Version="4.3.0" Condition="'$(TargetFramework.StartsWith(`netstandard2.`))' == 'true'" />
-    <PackageReference Include="System.Net.Security" Version="4.3.0" Condition="'$(TargetFramework.StartsWith(`netstandard2.`))' == 'true'" />
-    <PackageReference Include="System.IO.Pipes" Version="4.3.0" Condition="'$(TargetFramework.StartsWith(`netstandard2.`))' == 'true'" />
-    -->
   </ItemGroup>
 
   <ItemGroup>
@@ -86,6 +79,7 @@
     <None Include="..\README.md" Pack="true" PackagePath="\" />
   </ItemGroup>
 
+  <!--
   <ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
 		<PackageReference Include="Microsoft.AspNetCore.Components.Web">
       <Version>8.0.17</Version> 
@@ -98,6 +92,13 @@
     </PackageReference>
   </ItemGroup>
 
+  <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+    <PackageReference Include="Microsoft.AspNetCore.Components.Web">
+      <Version>10.0.0</Version>
+    </PackageReference>
+  </ItemGroup>
+  -->
+
   <Target Name="SetTFMAssemblyAttributesPath" BeforeTargets="GenerateTargetFrameworkMonikerAttribute">
     <PropertyGroup>
       <TargetFrameworkMonikerAssemblyAttributesPath>$(IntermediateOutputPath)$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)</TargetFrameworkMonikerAssemblyAttributesPath>
diff --git a/test/netstd/Client/Client.csproj b/test/netstd/Client/Client.csproj
index 991f072..2d619c2 100644
--- a/test/netstd/Client/Client.csproj
+++ b/test/netstd/Client/Client.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <LangVersion>latestMajor</LangVersion>
     <AssemblyName>Client</AssemblyName>
     <PackageId>Client</PackageId>
@@ -38,7 +38,9 @@
     <PackageReference Include="System.Net.Http.WinHttpHandler" Version="9.0.6" />
     <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
     <PackageReference Include="System.ServiceModel.Primitives" Version="8.1.2" />
+    <!--
     <PackageReference Include="System.Threading" Version="[4.3,)" />
+    -->
   </ItemGroup>
 
   <ItemGroup>
@@ -49,8 +51,8 @@
     <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
       <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
     </Exec>
-    <Exec Condition="Exists('$(PathToThrift)')" Command="&quot;$(PathToThrift)&quot; -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../ThriftTest.thrift" />
-    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../ThriftTest.thrift" />
-    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="&quot;$(PathToThrift)&quot; -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../ThriftTest.thrift" />
   </Target>
 </Project>
diff --git a/test/netstd/Server/Server.csproj b/test/netstd/Server/Server.csproj
index b64e9d0..5303578 100644
--- a/test/netstd/Server/Server.csproj
+++ b/test/netstd/Server/Server.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <LangVersion>latestMajor</LangVersion>
     <AssemblyName>Server</AssemblyName>
     <PackageId>Server</PackageId>
@@ -35,11 +35,13 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="System.IO.Pipes" Version="4.3.0" />
     <PackageReference Include="System.Net.Http.WinHttpHandler" Version="9.0.6" />
-    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
     <PackageReference Include="System.ServiceModel.Primitives" Version="8.1.2" />
+    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
+    <!--
+    <PackageReference Include="System.IO.Pipes" Version="4.3.0" />
     <PackageReference Include="System.Threading" Version="[4.3,)" />
+    -->
   </ItemGroup>
 
   <ItemGroup>
@@ -50,8 +52,8 @@
     <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
       <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
     </Exec>
-    <Exec Condition="Exists('$(PathToThrift)')" Command="&quot;$(PathToThrift)&quot; -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../ThriftTest.thrift" />
-    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../ThriftTest.thrift" />
-    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="&quot;$(PathToThrift)&quot; -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../ThriftTest.thrift" />
   </Target>
 </Project>
diff --git a/test/netstd/ThriftTest.sln b/test/netstd/ThriftTest.sln
index 45bc1f0..2c4649a 100644
--- a/test/netstd/ThriftTest.sln
+++ b/test/netstd/ThriftTest.sln
@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.32112.339
+# Visual Studio Version 18
+VisualStudioVersion = 18.0.11205.157 d18.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}"
 EndProject
@@ -21,6 +21,8 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.Compile.net9", "..\..\lib\netstd\Tests\Thrift.Compile.Tests\Thrift.Compile.net9\Thrift.Compile.net9.csproj", "{BB512CA7-D013-4CDC-AD2B-1E5EA121ED59}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.Compile.net10", "..\..\lib\netstd\Tests\Thrift.Compile.Tests\Thrift.Compile.net10\Thrift.Compile.net10.csproj", "{62BFDEC2-D23A-8800-09F5-B2467B2006A3}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -139,6 +141,18 @@
 		{BB512CA7-D013-4CDC-AD2B-1E5EA121ED59}.Release|x64.Build.0 = Release|Any CPU
 		{BB512CA7-D013-4CDC-AD2B-1E5EA121ED59}.Release|x86.ActiveCfg = Release|Any CPU
 		{BB512CA7-D013-4CDC-AD2B-1E5EA121ED59}.Release|x86.Build.0 = Release|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Debug|x64.Build.0 = Debug|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Debug|x86.Build.0 = Debug|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Release|x64.ActiveCfg = Release|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Release|x64.Build.0 = Release|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Release|x86.ActiveCfg = Release|Any CPU
+		{62BFDEC2-D23A-8800-09F5-B2467B2006A3}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/tutorial/netstd/Client/Client.csproj b/tutorial/netstd/Client/Client.csproj
index a18d3d0..64357d1 100644
--- a/tutorial/netstd/Client/Client.csproj
+++ b/tutorial/netstd/Client/Client.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <LangVersion>latestMajor</LangVersion>
     <AssemblyName>Client</AssemblyName>
     <PackageId>Client</PackageId>
diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs
index 93175fd..082e767 100644
--- a/tutorial/netstd/Client/Program.cs
+++ b/tutorial/netstd/Client/Program.cs
@@ -115,16 +115,20 @@
         {
             var numClients = GetNumberOfClients(args);
 
-            Logger.LogInformation("Selected # of clients: {numClients}", numClients);
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("Selected # of clients: {numClients}", numClients);
 
             var transport = GetTransport(args);
-            Logger.LogInformation("Selected client transport: {transport}", transport);
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("Selected client transport: {transport}", transport);
 
             var protocol = MakeProtocol( args, MakeTransport(args));
-            Logger.LogInformation("Selected client protocol: {GetProtocol(args)}", GetProtocol(args));
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("Selected client protocol: {GetProtocol(args)}", GetProtocol(args));
 
             var mplex = GetMultiplex(args);
-            Logger.LogInformation("Multiplex {mplex}", mplex);
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("Multiplex {mplex}", mplex);
 
             var tasks = new Task[numClients];
             for (int i = 0; i < numClients; i++)
@@ -133,8 +137,7 @@
                 tasks[i] = task;
             }
 
-            Task.WaitAll(tasks,cancellationToken);
-            await Task.CompletedTask;
+            Task.WaitAll(tasks, cancellationToken);
         }
 
         private static bool GetMultiplex(string[] args)
@@ -238,7 +241,8 @@
         {
             var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':').Skip(1).Take(1).FirstOrDefault();
 
-            Logger.LogInformation("Selected # of clients: {numClients}", numClients);
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("Selected # of clients: {numClients}", numClients);
 
             if (int.TryParse(numClients, out int c) && (0 < c) && (c <= 100))
                 return c;
@@ -258,7 +262,8 @@
             }
             else
             {
-                Logger.LogError("Root path of {path} not found", Directory.GetCurrentDirectory());
+                if (Logger.IsEnabled(LogLevel.Error))
+                    Logger.LogError("Root path of {path} not found", Directory.GetCurrentDirectory());
                 throw new Exception($"Root path of {Directory.GetCurrentDirectory()} not found");
             }
         }
@@ -315,7 +320,8 @@
                 }
                 catch (Exception ex)
                 {
-                    Logger.LogError("{ex}",ex);
+                    if (Logger.IsEnabled(LogLevel.Error))
+                        Logger.LogError("{ex}",ex);
                 }
                 finally
                 {
@@ -324,7 +330,8 @@
             }
             catch (TApplicationException x)
             {
-                Logger.LogError("{x}",x);
+                if (Logger.IsEnabled(LogLevel.Error))
+                    Logger.LogError("{x}",x);
             }
         }
 
@@ -332,14 +339,18 @@
         {
             await client.OpenTransportAsync(cancellationToken);
 
-            // Async version
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("{client.ClientId} Ping()", client.ClientId);
 
-            Logger.LogInformation("{client.ClientId} Ping()", client.ClientId);
             await client.ping(cancellationToken);
 
-            Logger.LogInformation("{client.ClientId} Add(1,1)", client.ClientId);
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("{client.ClientId} Add(1,1)", client.ClientId);
+
             var sum = await client.add(1, 1, cancellationToken);
-            Logger.LogInformation("{client.ClientId} Add(1,1)={sum}", client.ClientId, sum);
+
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("{client.ClientId} Add(1,1)={sum}", client.ClientId, sum);
 
             var work = new Work
             {
@@ -350,13 +361,18 @@
 
             try
             {
-                Logger.LogInformation("{client.ClientId} Calculate(1)", client.ClientId);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{client.ClientId} Calculate(1)", client.ClientId);
+
                 await client.calculate(1, work, cancellationToken);
-                Logger.LogInformation("{client.ClientId} Whoa we can divide by 0", client.ClientId);
+
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{client.ClientId} Whoa we can divide by 0", client.ClientId);
             }
             catch (InvalidOperation io)
             {
-                Logger.LogInformation("{client.ClientId} Invalid operation: {io}", client.ClientId, io);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{client.ClientId} Invalid operation: {io}", client.ClientId, io);
             }
 
             work.Op = Operation.SUBTRACT;
@@ -365,20 +381,31 @@
 
             try
             {
-                Logger.LogInformation("{client.ClientId} Calculate(1)", client.ClientId);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{client.ClientId} Calculate(1)", client.ClientId);
+
                 var diff = await client.calculate(1, work, cancellationToken);
-                Logger.LogInformation("{client.ClientId} 15-10={diff}", client.ClientId, diff);
+
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{client.ClientId} 15-10={diff}", client.ClientId, diff);
             }
             catch (InvalidOperation io)
             {
-                Logger.LogInformation("{client.ClientId} Invalid operation: {io}", client.ClientId, io);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{client.ClientId} Invalid operation: {io}", client.ClientId, io);
             }
 
-            Logger.LogInformation("{client.ClientId} GetStruct(1)", client.ClientId);
-            var log = await client.getStruct(1, cancellationToken);
-            Logger.LogInformation("{client.ClientId} Check log: {log.Value}", client.ClientId, log.Value);
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("{client.ClientId} GetStruct(1)", client.ClientId);
 
-            Logger.LogInformation("{client.ClientId} Zip() with delay 100mc on server side", client.ClientId);
+            var log = await client.getStruct(1, cancellationToken);
+
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("{client.ClientId} Check log: {log.Value}", client.ClientId, log.Value);
+
+            if (Logger.IsEnabled(LogLevel.Information))
+                Logger.LogInformation("{client.ClientId} Zip() with delay 100mc on server side", client.ClientId);
+
             await client.zip(cancellationToken);
         }
 
diff --git a/tutorial/netstd/Interfaces/Interfaces.csproj b/tutorial/netstd/Interfaces/Interfaces.csproj
index 7ebe5c7..122866c 100644
--- a/tutorial/netstd/Interfaces/Interfaces.csproj
+++ b/tutorial/netstd/Interfaces/Interfaces.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <AssemblyName>Interfaces</AssemblyName>
     <PackageId>Interfaces</PackageId>
     <Version>0.23.0.0</Version>
@@ -42,8 +42,8 @@
     <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
       <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
     </Exec>
-    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../tutorial.thrift" />
-    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../tutorial.thrift" />
-    <Exec Condition="Exists('./../../../compiler/cpp/thrift')" Command="./../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net9 -r ./../../tutorial.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../tutorial.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../tutorial.thrift" />
+    <Exec Condition="Exists('./../../../compiler/cpp/thrift')" Command="./../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial,net10 -r ./../../tutorial.thrift" />
   </Target>
 </Project>
diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs
index a3b12fc..004ea77 100644
--- a/tutorial/netstd/Server/Program.cs
+++ b/tutorial/netstd/Server/Program.cs
@@ -19,6 +19,7 @@
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
 using shared;
 using System;
@@ -224,13 +225,14 @@
 
             try
             {
-                Logger.LogInformation(
-                    "TSimpleAsyncServer with \n{transport} transport\n{buffering} buffering\nmultiplex = {multiplex}\n{protocol} protocol",
-                    transport,
-                    buffering,
-                    multiplex ? "yes" : "no",
-                    protocol
-                    );
+                if( Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation(
+                        "TSimpleAsyncServer with \n{transport} transport\n{buffering} buffering\nmultiplex = {multiplex}\n{protocol} protocol",
+                        transport,
+                        buffering,
+                        multiplex ? "yes" : "no",
+                        protocol
+                        );
 
                 var server = new TSimpleAsyncServer(
                     itProcessorFactory: new TSingletonProcessorFactory(processor),
@@ -247,7 +249,8 @@
             }
             catch (Exception x)
             {
-                Logger.LogInformation("{x}",x);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("{x}",x);
             }
         }
 
@@ -315,13 +318,16 @@
                     .AddEnvironmentVariables(prefix: "ASPNETCORE_")
                     .Build();
 
-                var host = new WebHostBuilder()
-                    .UseConfiguration(config)
-                    .UseKestrel()
-                    .UseUrls("http://localhost:9090")
-                    .UseContentRoot(Directory.GetCurrentDirectory())
-                    .UseStartup<Startup>()
-                    .ConfigureLogging((ctx,logging) => LoggingHelper.ConfigureLogging(logging))
+                var host = new HostBuilder().
+                    ConfigureWebHost(webhostbuilder => {
+                        webhostbuilder.UseConfiguration(config)
+                                      .UseUrls("http://localhost:9090")
+                                      .UseContentRoot(Directory.GetCurrentDirectory())
+                                      .UseStartup<Startup>()
+                                      .UseKestrel()
+                                      .ConfigureLogging((ctx, logging) => LoggingHelper.ConfigureLogging(logging))
+                                      ;
+                    })
                     .Build();
 
                 Logger.LogTrace("test");
@@ -373,25 +379,27 @@
             public async Task<SharedStruct> getStruct(int key,
                 CancellationToken cancellationToken)
             {
-                Logger.LogInformation("GetStruct({key})", key);
-                return await Task.FromResult(_log[key]);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("GetStruct({key})", key);
+                return _log[key];
             }
 
             public async Task ping(CancellationToken cancellationToken)
             {
                 Logger.LogInformation("Ping()");
-                await Task.CompletedTask;
             }
 
             public async Task<int> add(int num1, int num2, CancellationToken cancellationToken)
             {
-                Logger.LogInformation("Add({num1},{num2})", num1, num2);
-                return await Task.FromResult(num1 + num2);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("Add({num1},{num2})", num1, num2);
+                return num1 + num2;
             }
 
             public async Task<int> calculate(int logid, Work? w, CancellationToken cancellationToken)
             {
-                Logger.LogInformation("Calculate({logid}, [{w.Op},{w.Num1},{w.Num2}])", logid, w?.Op, w?.Num1, w?.Num2);
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("Calculate({logid}, [{w.Op},{w.Num1},{w.Num2}])", logid, w?.Op, w?.Num1, w?.Num2);
 
                 int val;
                 switch (w?.Op)
@@ -441,8 +449,7 @@
                 };
 
                 _log[logid] = entry;
-
-                return await Task.FromResult(val);
+                return val;
             }
 
             public async Task zip(CancellationToken cancellationToken)
@@ -456,12 +463,14 @@
         {
             public async Task<SharedStruct> getStruct(int key, CancellationToken cancellationToken)
             {
-                Logger.LogInformation("GetStruct({key})", key);
-                return await Task.FromResult(new SharedStruct()
+                if (Logger.IsEnabled(LogLevel.Information))
+                    Logger.LogInformation("GetStruct({key})", key);
+
+                return new SharedStruct()
                 {
                     Key = key,
                     Value = "GetStruct"
-                });
+                };
             }
         }
     }
diff --git a/tutorial/netstd/Server/Server.csproj b/tutorial/netstd/Server/Server.csproj
index 940b931..805ee0a 100644
--- a/tutorial/netstd/Server/Server.csproj
+++ b/tutorial/netstd/Server/Server.csproj
@@ -19,7 +19,7 @@
   -->
 
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <LangVersion>latestMajor</LangVersion>
     <AssemblyName>Server</AssemblyName>
     <PackageId>Server</PackageId>