我们正在考虑将计算某些结果的工作与提交这些结果的工作分开的API模式是:
interface IResults { }
class Results : IResults { }
Task<IResults> CalculateResultsAsync(CancellationToken ct)
{
return Task.Run<IResults>(() => new Results(), ct);
}
void CommitResults(IResults iresults)
{
Results results = (Results)iresults;
// Commit the results
}
这将允许客户端具有启动某些结果计算的UI,并知道计算何时准备好,然后在那时决定是否提交结果。这主要是为了帮助我们处理在计算过程中UI将允许用户取消操作的情况。我们希望确保:
CalculateResultsAsync
任务完成,我们将取消取消用户界面,只要用户没有取消,请继续并调用提交方法。IResults
传递给CommitResults
之外,客户永远不会使用IResults
。问题: 一般的问题是:这是一个好方法吗?具体做法是:
答案 0 :(得分:3)
这是非常标准模式(如果不是理想模式),尤其是当您的Results对象是不可变的时。我们定期在Visual Studio代码库中的TPL使用代码中执行此操作。当您的异步/并行逻辑处理数据时,总是存在很多快乐,并且变异的废话与此不同。
如果您熟悉或听说过“Roslyn”项目,这是我们实际上鼓励人们使用的模式。这个想法是重构可以在后台异步处理并产生一个对象,就像你的结果一样,表示正在应用重构的结果。然后,在UI线程上,任何人都可以使用其中一个结果对象并应用它,然后更新所有文件以包含新文本。
我确实发现整个IResults / Results的事情有点奇怪 - 目前尚不清楚你是否使用它来隐藏自己的实现。如果空接口和强制转换错误,您可以考虑向IResult添加一个提交方法,结果对象实现该方法。由你决定。
答案 1 :(得分:0)
我不确定为什么你需要这种模式。对我来说,似乎如果你在开始提交之前检查CancellationToken
,你将得到完全相同的结果,界面更简单。