如何解决.NET3.5中System.Threading.Tasks与Net35.Threading.Tasks的冲突?
我正在维护一个基于.NET3.5的老旧应用,需要使用System.Net.Http,但该组件是.NET3.5之后才引入的。为解决这个问题,我安装了Rackspace.HttpClient35包,现在能正常创建HttpClient并使用其功能,但安装后引发了System.Threading.Tasks库的冲突。所有使用Task<string>的地方都会出现以下错误:
Error CS0433 The type 'Task' exists in both 'Net35.Threading.Tasks, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b3b1c0202c0d6a87' and 'System.Threading.Tasks.NET35, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null'
我尝试用完整路径System.Threading.Tasks.Task<string>指定类型,但错误依然存在。
已尝试的操作
1. 修改csproj文件显式添加System.Threading.Tasks库
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net35</TargetFramework> <NullableContextOptions>enable</NullableContextOptions> <LangVersion>8.0</LangVersion> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <WarningLevel>9999</WarningLevel> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <WarningLevel>9999</WarningLevel> </PropertyGroup> <ItemGroup> <PackageReference Include="Net4x.Serilog" Version="2.12.1-at20230411063734" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Rackspace.HttpClient35" Version="1.0.0-beta003"> <ExcludeAssets>runtime; contentfiles; analyzers; build</ExcludeAssets> <IncludeAssets>compile; native</IncludeAssets> </PackageReference> <PackageReference Include="System.Threading.Tasks" Version="3.0.0" /> </ItemGroup> <ItemGroup> <Reference Include="System.Configuration" /> <Reference Include="System.Web" /> <Reference Include="System.Threading"> <HintPath>path\net35\System.Threading.Tasks.NET35.dll</HintPath> <Private>False</Private> </Reference> </ItemGroup> </Project>
2. 在app.config中配置绑定重定向
<?xml version="1.0"?> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Net35.Threading.Tasks" publicKeyToken="b3b1c0202c0d6a87" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
由于是遗留项目无法升级.NET版本,请问如何强制代码使用System.Threading.Tasks?
解决方案
1. 排除Rackspace.HttpClient35包中的冲突依赖
修改Rackspace.HttpClient35的PackageReference,直接排除它依赖的Net35.Threading.Tasks包,避免引入冲突程序集:
<PackageReference Include="Rackspace.HttpClient35" Version="1.0.0-beta003"> <ExcludeAssets>runtime; contentfiles; analyzers; build</ExcludeAssets> <IncludeAssets>compile; native</IncludeAssets> <ExcludePackageReferences>Net35.Threading.Tasks</ExcludePackageReferences> </PackageReference>
2. 调整程序集引用优先级
移除手动添加的System.Threading引用,因为System.Threading.Tasks包已包含正确程序集,手动引用会导致优先级混乱。同时将System.Threading.Tasks的PackageReference放在Rackspace.HttpClient35之前,让编译器优先使用它的类型:
<ItemGroup> <PackageReference Include="Net4x.Serilog" Version="2.12.1-at20230411063734" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <!-- 优先声明System.Threading.Tasks --> <PackageReference Include="System.Threading.Tasks" Version="3.0.0" /> <PackageReference Include="Rackspace.HttpClient35" Version="1.0.0-beta003"> <ExcludeAssets>runtime; contentfiles; analyzers; build</ExcludeAssets> <IncludeAssets>compile; native</IncludeAssets> <ExcludePackageReferences>Net35.Threading.Tasks</ExcludePackageReferences> </PackageReference> </ItemGroup> <ItemGroup> <Reference Include="System.Configuration" /> <Reference Include="System.Web" /> <!-- 移除手动添加的System.Threading引用 --> </ItemGroup>
3. 修正绑定重定向配置
确保所有冲突程序集都指向目标版本,修改app.config:
<?xml version="1.0"?> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!-- 强制Net35.Threading.Tasks指向System.Threading.Tasks.NET35的版本 --> <dependentAssembly> <assemblyIdentity name="Net35.Threading.Tasks" publicKeyToken="b3b1c0202c0d6a87" /> <bindingRedirect oldVersion="0.0.0.0-1.0.0.0" newVersion="3.0.0.0" /> <codeBase version="3.0.0.0" href="System.Threading.Tasks.NET35.dll" /> </dependentAssembly> <!-- 统一System.Threading.Tasks.NET35的版本 --> <dependentAssembly> <assemblyIdentity name="System.Threading.Tasks.NET35" publicKeyToken="null" /> <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
4. 使用extern alias强制指定程序集
如果以上方法无效,通过别名区分两个程序集:
- 在csproj中给
System.Threading.Tasks添加别名:
<PackageReference Include="System.Threading.Tasks" Version="3.0.0"> <Aliases>STT</Aliases> </PackageReference>
- 在代码文件顶部声明别名并指定类型:
extern alias STT; using Task = STT::System.Threading.Tasks.Task;
此后代码中所有Task都会指向System.Threading.Tasks中的类型。
5. 清理重建项目
删除项目的bin、obj文件夹,重新生成解决方案,确保旧程序集引用被彻底移除。
内容的提问来源于stack exchange,提问作者the_badev

