我正在将一些异步/等待代码转换为链式任务,这样我就可以在发布的框架中使用它。await代码如下所示
public async Task<TraumMessage> Get() {
var message = await Invoke("GET");
var memorized = await message.Memorize();
return memorized;
}哪里
Task<TraumMessage> Invoke(string verb) {}
Task<TraumMessage> Memorize() {}我希望将Invoke和Memorize链接起来,以返回Memorize生成的任务,但结果是生成了一个Task<Task<TraumMessage>。我最终得到的解决方案是一个TaskCompletionSource<TraumMessage>作为我的信号:
public Task<TraumMessage> Get() {
var completion = new TaskCompletionSource<TraumMessage>();
Invoke("GET").ContinueWith( t1 => {
if(t1.IsFaulted) {
completion.SetException(t1.Exception);
return;
}
t1.Result.Memorize().ContinueWith( t2 => {
if(t2.IsFaulted) {
completion.SetException(t2.Exception);
return;
}
completion.SetResult(t2.Result);
});
});
return completion.Task;
}有没有一种方法可以在没有TaskCompletionSource的情况下实现这一点
发布于 2011-07-31 01:10:46
我认为这几乎是实现你想要的东西的唯一方法。延续API不支持将不同的任务链接在一起,因此您必须使用TaskCompletionSource,就像您必须协调工作一样。
我没有在这台机器上安装Async CTP,但是你为什么不用一个反编译器(或者ILDASM,如果你知道怎么读IL的话)来看看它在做什么。我敢打赌,它在幕后做的事情和你的TCS代码非常相似。
发布于 2012-04-25 21:20:05
是的,这个框架提供了一个方便的Unwrap()扩展方法来满足您的需求。
Invoke("GET").ContinueWith( t => t.Result.Memorize() ).Unwrap();如果你正在进行取消操作,那么显然你需要将取消令牌传递到适当的位置。
发布于 2011-09-04 12:09:25
您可以使用附加的子任务。只有在所有子任务都完成时,父任务才会转换为已完成状态。异常将传播到父任务。您将需要一个结果容器,因为结果将在父任务的委托完成后分配,但将在父任务继续运行时设置。
如下所示:
public class Holder<T> where T: class
{
public T Value { get; set; }
}
public Task<Holder<TraumMessage>> Get() {
var invokeTask = Invoke("GET");
var result = invokeTask.ContinueWith<Holder<TraumMessage>>(t1 => {
var holder = new Holder<TraumMessage>();
var memorizeTask = t1.Result.Memorize();
memorizeTask.ContinueWith(t2 => {
holder.Value = t2.Result;
}, TaskContinuationOptions.AttachedToParent);
return holder;
});
return result;
}https://stackoverflow.com/questions/6884470
复制相似问题