Task.WhenAll 订单的结果是否有保证?
Is result of Task.WhenAll order guaranteed?
从下面的测试可以看出,当前版本的框架保证输出顺序与输入任务相同
async Task<string> GetString1()
{
await Task.Delay(2000);
return "1";
}
async Task<string> GetString2()
{
await Task.Delay(1000);
return "2";
}
var results = await Task.WhenAll(GetString1(), GetString2());
//now we have results[0] == "1" results[1] == "2"
但是,来自 the documentation I can't find anything about this behavior, which means it's not document-guaranteed. From the opinions of answers in this question:
我需要在输出中加入“order flags”吗?例如将示例代码更改为以下内容:
class OrderTaskResult<T>
{
public OrderTaskResult(int order, T value)
{
this.Order = order;
this.Value = value;
}
public int Order { get; private set; }
public T Value { get; private set; }
}
async Task<OrderTaskResult<string>> GetString1()
{
await Task.Delay(2000);
return new OrderTaskResult<string>(1, "1");
}
您正在查看错误重载的文档。
如果您查看实际上 returns 结果的 overload,您会看到:
The Task<TResult>.Result
property of the returned task will be set to an array containing all of the results of the supplied tasks in the same order as they were provided
回答你的第二个问题,虽然在这个特殊情况下认识到它现在没有实际意义 -
Q2: (maybe primary opinion-based) Is it really bad practice to code depending on undocumented behaviors, especially when some behaviors have little possibility to be changed? Sometimes you need to add lots of code to avoid undocumented behaviors.
要给出规范的工程答案 - 这取决于。您需要权衡当前使用更简单代码的好处和将来脚下的地毯被拉走的风险。
一方面,“technical debt”是您可以通过继续阅读以建立您的直觉中获益的东西 -
Technical debt (also known as design debt or code debt, but can be also related to other technical endeavors) is a concept in software development that reflects the implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer.
另一方面,通过以模块化和松散耦合的方式构建代码库,您也许可以将风险降低到可接受的程度 - 如果您遵循 SOLID 给出的指导,设计原则,你可能无论如何都会这样做。或者,如果您采用更实用的路线,您可以尝试借鉴 Mark Seemann 的 Impureim sandwich,这对于保持您的核心领域逻辑与应用程序细节分离有很长的路要走,因为下一次炒作或弃用特定的传递技术。
从下面的测试可以看出,当前版本的框架保证输出顺序与输入任务相同
async Task<string> GetString1()
{
await Task.Delay(2000);
return "1";
}
async Task<string> GetString2()
{
await Task.Delay(1000);
return "2";
}
var results = await Task.WhenAll(GetString1(), GetString2());
//now we have results[0] == "1" results[1] == "2"
但是,来自 the documentation I can't find anything about this behavior, which means it's not document-guaranteed. From the opinions of answers in this question:
我需要在输出中加入“order flags”吗?例如将示例代码更改为以下内容:
class OrderTaskResult<T>
{
public OrderTaskResult(int order, T value)
{
this.Order = order;
this.Value = value;
}
public int Order { get; private set; }
public T Value { get; private set; }
}
async Task<OrderTaskResult<string>> GetString1()
{
await Task.Delay(2000);
return new OrderTaskResult<string>(1, "1");
}
您正在查看错误重载的文档。
如果您查看实际上 returns 结果的 overload,您会看到:
The
Task<TResult>.Result
property of the returned task will be set to an array containing all of the results of the supplied tasks in the same order as they were provided
回答你的第二个问题,虽然在这个特殊情况下认识到它现在没有实际意义 -
Q2: (maybe primary opinion-based) Is it really bad practice to code depending on undocumented behaviors, especially when some behaviors have little possibility to be changed? Sometimes you need to add lots of code to avoid undocumented behaviors.
要给出规范的工程答案 - 这取决于。您需要权衡当前使用更简单代码的好处和将来脚下的地毯被拉走的风险。
一方面,“technical debt”是您可以通过继续阅读以建立您的直觉中获益的东西 -
Technical debt (also known as design debt or code debt, but can be also related to other technical endeavors) is a concept in software development that reflects the implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer.
另一方面,通过以模块化和松散耦合的方式构建代码库,您也许可以将风险降低到可接受的程度 - 如果您遵循 SOLID 给出的指导,设计原则,你可能无论如何都会这样做。或者,如果您采用更实用的路线,您可以尝试借鉴 Mark Seemann 的 Impureim sandwich,这对于保持您的核心领域逻辑与应用程序细节分离有很长的路要走,因为下一次炒作或弃用特定的传递技术。