C# 在.NET标准上实现异步返回类型
大家好,我正在尝试使用.NetCore框架的C# 在.NET标准上实现异步返回类型,c#,async-await,task-parallel-library,.net-standard,C#,Async Await,Task Parallel Library,.net Standard,大家好,我正在尝试使用.NetCore框架的asynchmethodbuilderAttribute创建我自己的Task类型。 到目前为止,netcore我的自定义Type工作正常,可以等待它,我可以将它作为异步[MyTypeName]MyMethod()而不是任务返回 但是在.NetStandard 2.0中,该属性不存在,我尝试实现它:我用该属性修饰了我的等待类型,但它仍然不允许我使用它:“异步方法的返回类型必须为void,Task,Task” 到目前为止,我可以在。netcore中使用类似
asynchmethodbuilderAttribute
创建我自己的Task
类型。到目前为止,
netcore
我的自定义Type
工作正常,可以等待它
,我可以将它作为异步[MyTypeName]MyMethod()
而不是任务
返回但是在
.NetStandard 2.0
中,该属性不存在,我尝试实现它:我用该属性修饰了我的等待类型,但它仍然不允许我使用它:
“异步方法的返回类型必须为void,Task,Task”
到目前为止,我可以在。netcore
中使用类似的东西,它可以工作
public async Task WrapperMethod(){
int result=await GetIntAsync();
}
public async Errand<int> GetIntAsync()
{
await Task.Delay(1000);
return 3;
}
下面是自定义类型和
异步方法生成器的实现。等待器在这种情况下并不重要,但如果需要,我可以提供源代码。
我的任务
类类型
[AsyncMethodBuilder(typeof(Builder))]
public partial class Errand {
private readonly Builder mbuilder;
public Errand() {
}
internal Errand(Builder methodBuilder) => this.mbuilder = methodBuilder;
private readonly HashSet<Awaiter> awaiters = new HashSet<Awaiter>();
protected bool isCompleted = false;
public Awaiter GetAwaiter() {
Awaiter result = new Awaiter(this);
this.awaiters.Add(result);
return result;
}
}
要使它在.Net标准中工作,我还应该添加什么?属性的源文件在哪里并不重要,但它确实需要有正确的命名空间声明:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
public sealed class AsyncMethodBuilderAttribute : Attribute
{
public AsyncMethodBuilderAttribute(Type builderType) =>
BuilderType = builderType;
public Type BuilderType { get; }
}
}
@达斯宾莱特:是的,你可以。这就像ExtensionAttribute
——编译器希望在正确的名称空间中找到该属性,但会在任何可以找到它的地方使用它。我不推荐它(更喜欢使用nuget包),但它是可行的。我猜OP没有使用C#7编译器,但这很难说。请注意,该属性必须在System.Runtime.CompilerServices
命名空间中声明-我们无法从发布的代码中判断它是否在实际声明的位置。@DaisyShipton这实际上是正确的答案-OP将它放在了错误的命名空间中。@Evk:可能是。。。但我们不能确定。我不确定我是否想根据直觉添加答案。@Bercovicadrian但是你能将你的属性放在正确的名称空间中,并告诉我们这是否解决了问题吗?噢,你说得对:D对不起,我想我必须以某种方式将它放在SDK的源代码中。
public partial class Builder {
#region " Compiler integration "
public static Builder Create() {
return new Builder();
}
protected IAsyncStateMachine myStateMachine;
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine {
this.myStateMachine = stateMachine;
this.errand = new Errand(this);
stateMachine.MoveNext();
}
public void SetException(Exception ex) {
}
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine machine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine {
var foo = machine as IAsyncStateMachine;
awaiter.OnCompleted(() => { foo.MoveNext(); });
}
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine machine)where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine {
IAsyncStateMachine asyncMachine = machine as IAsyncStateMachine;
awaiter.OnCompleted(() => asyncMachine.MoveNext());
}
private Errand errand;
public Errand Task { get { return this.errand; } }
public void SetStateMachine(IAsyncStateMachine stateMachine) {
}
public void SetResult() {
}
#endregion
// internal void AddAwaiter(Awaiter awaiter) => this.awaiters.Add(awaiter);
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
public sealed class AsyncMethodBuilderAttribute : Attribute
{
public AsyncMethodBuilderAttribute(Type builderType) =>
BuilderType = builderType;
public Type BuilderType { get; }
}
}