C# 异步初始化局部变量
使用.Net 4.5+中提供的异步功能,有没有一种方法可以同时初始化多个局部变量,而不必分两步执行?是否有其他方法延迟阻止父级直到尝试取消引用等待的变量 示例:我有一个方法,其中给了我三个ID,用于从三个独立的服务获取对象。每项服务都会花费大量的时间返回,我希望尽量减少所需的时钟时间。对象的创建没有相互依赖关系 我能做的是:C# 异步初始化局部变量,c#,async-await,C#,Async Await,使用.Net 4.5+中提供的异步功能,有没有一种方法可以同时初始化多个局部变量,而不必分两步执行?是否有其他方法延迟阻止父级直到尝试取消引用等待的变量 示例:我有一个方法,其中给了我三个ID,用于从三个独立的服务获取对象。每项服务都会花费大量的时间返回,我希望尽量减少所需的时钟时间。对象的创建没有相互依赖关系 我能做的是: string MyFunc(long userId, long moduleId, long targetId) { var userTask = _userRep
string MyFunc(long userId, long moduleId, long targetId) {
var userTask = _userRepo.Get(userId);
var moduleTask = _moduleRepo.Get(moduleId);
var targetTask = _targetRepo.Get(targetId);
var user = await userTask;
var module = await moduleTask;
var action = module.GetActionFor(user);
var target = await targetTask;
action.ApplyTo(target);
return string.Format("{0} begins {1} at {2}",
user.Name,
action.Description,
target.Location);
}
如何删除中间任务任务变量
澄清:
我在找更简洁的东西。除了初始分配,我不需要这些任务,并且在操作的剩余部分中会多次使用结果
这样做的结果是基本上同步运行代码。如果每个Get语句需要1秒才能返回,则该块需要3秒才能完成:
var user = await _userRepo.Get(userId);
var module = await _moduleRepo.Get(moduleId);
var target = await _targetRepo.Get(targetId);
执行以下操作会导致代码变得难以阅读,尤其是当需要多次使用对象时:
var user = _userRepo.Get(userId);
var module = _moduleRepo.Get(moduleId);
var target = _targetRepo.Get(targetId);
var action = (await module).GetActionFor(await user);
action.ApplyTo(await target);
var formattedString = string.Format("{0} begins {1} at {2}",
(await user).Name,
action.Description,
(await target).Location);
如果每个
任务
实例具有相同的泛型类型参数(例如,任务
),则可以在一行中完成所有操作:
object[] results = await Task.WhenAll<object>(_userRepo.Get(userId),
_moduleRepo.Get(moduleId),
_targetRepo.Get(targetId));
return string.Format("{0} begins {1} at {2}",
((User)results [0]).Name,
((Module)results [1]).Description,
((Target)results [2]).Location);
object[]results=wait Task.WhenAll(_userRepo.Get(userId),
_moduleRepo.Get(moduleId),
_targetRepo.Get(targetId));
返回string.Format(“{0}从{1}开始于{2}”,
((用户)结果[0])。名称,
((模块)结果[1])。说明,
((目标)结果[2])。位置);
根据:
创建一个任务,该任务将在所有提供的任务完成后完成
我不相信有一个好的方法可以得到你想要的(至少没有一些严肃的编译时元编程) 我能找到的最接近的答案是:
User user = null;
Module module = null;
Target target = null;
await RunAll(
async () => user = await _userRepo.Get(userId),
async () => module = await _moduleRepo.Get(moduleId),
async () => target = await _targetRepo.Get(targetId));
var action = module.GetActionFor(user);
action.ApplyTo(target);
var formattedString = string.Format("{0} begins {1} at {2}",
user.Name,
action.Description,
target.Location);
其中RunAll()
的定义如下:
static Task RunAll(params Func<Task>[] funcs)
{
return Task.WhenAll(funcs.Select(f => f()));
}
static Task RunAll(params Func[]funcs)
{
返回Task.WhenAll(funcs.Select(f=>f());
}
um,No:无法将类型“void”隐式转换为“object[]”
@psaxton请参见编辑。尝试调用Task.whalll(…)
。请注意,所有输入任务都必须返回一个任务
'a'以进行工作,但将repos更改为返回对象
似乎不是正确的方法。编写包装器方法来强制转换结果不会更好。您到底想实现什么?除了使用Task.whalll
并发查询数据库之外,我看不出有什么问题。代码中没有任何中间任务<代码>等待不创建中间任务,它等待现有任务完成。也许真正的问题是“我如何等待多个任务完成?”@PanagiotisKanavos我想中间任务指的是中间变量。我知道使用Task.whalll
等待多个任务,所以问题不是等待多个任务完成。我要寻找的是类似于埃菲尔铁塔中的SCOOP的东西——当变量第一次被解引用时自动等待Task.Result
。令人遗憾的是,第二个代码块将在下一个语句之前产生并阻塞,而不是等待等待的变量被解引用以产生。这是用于日志记录的吗?(它看起来有点像一行日志/跟踪/调试代码)。。。如果是这样的话,我可以建议,与其从任务返回行并处理潜在的继续问题,等等,为什么不通过某种事件中介逻辑将字符串作为消息接收呢?例如,EventAggregator
可以很好地满足这一需求。异步代码可以在最后一行中发布事件和负载字符串,而不是返回字符串。在事件处理程序中,您可以集中精力处理异步传入的数据。@code4life上面的代码仅用于示例。我可以看到它看起来像日志代码。如果更具体一些会有所帮助,那么实际的代码库就是聚合微服务操作/响应和数据库获取/更新。即使对于CodeReview帖子,尝试发布一个工作示例也会持续很长时间。