问题描述
我目前正在研究模拟类库,其他程序员将使用该类来创建动态模拟时间轴并运行这些模拟。
从某种意义上讲,这是通过让库的用户指定模拟时间内特定点的动作来完成的。
但是我现在遇到了一个问题,即用户创建的动作可能是异步的,也可能是异步的。为了使仿真保持一致,尽管我需要同步执行两个变体。我把问题归结为一个非常简单的例子:
class Program
{
static void Main()
{
Action action = ActionFromUser();
action();
Console.WriteLine("2");
Console.ReadKey();
}
static Action ActionFromUser()
{
Random rng = new Random();
if (rng.Next(0,2) == 0) // 50/50
{
return async () =>
{
await Task.Delay(1000);
Console.WriteLine("1");
};
}
else
{
return () =>
{
Thread.Sleep(1000);
Console.WriteLine("1");
};
}
}
}
现在的问题归结为输出取决于操作是异步还是同步,这是我要摆脱的行为。
该操作将始终没有参数且没有返回值。
我不不想使用反射(action.Method.IsDefined(typeof(AsyncStateMachineAttribute),...
)。
我尝试从Action
切换到delegate
(Func
似乎不是一个好选择,因为我必须指定一个返回值类型),但是我在那里什么都没找到那会帮助我。
解决方法
Action
上的异步lambda 是async void
。您极不可能想要这个。如有疑问,请将其更改为Func<Task>
,并在 synchronous 结果上返回一个完成的任务,然后将结果await
返回。
注意:这是一个人为的示例,我想您的代码有很大不同,但是它说明了这一点:
static Func<Task> FromUserAsync()
{
Random rng = new Random();
if (rng.Next(0,2) == 0) // 50/50
{
return async () =>
{
await Task.Delay(1000);
Console.WriteLine("1");
};
}
else
{
return () =>
{
Thread.Sleep(1000);
Console.WriteLine("1");
return Task.CompletedTask;
};
}
}
最后一点,您可能应该使用Task.FromException