使用任务并行库来翻译void任务的异常 [英] Translating exceptions for void Tasks with Task Parallel Library a la await
问题描述
我需要翻译从任务< T>
发出的异常,其方式与对于普通同步代码执行以下操作相同:
I need to translate an exception emanating from a Task<T>
in the same manner that doing the following would for normal synchronous code:
try {
client.Call();
} catch(FaultException ex) {
if (ex.<Some check>)
throw new Exception("translated");
}
但是,我想要这样做是异步的,即调用实际上是
任务CallAsync()
。
However, I want to do this asynchronously, i.e., Call
above is actually Task CallAsync()
.
方法将如下所示:
async Task CallAndTranslate()
{
try{
await client.CallAsync();
} catch(FaultException ex) {
if (ex.FaultCode ...)
throw new Exception("translated");
}
}
但我现在使用C#4。
But I'm using C# 4 for now.
所以,我可以做什么,因为我想要触发一个任务,但有(TPL)故障被翻译,然后再次暴露整个事情作为任务< T>
?
So what can I do given that I want to trigger a Task but have the (TPL) Fault be translated and then expose the whole thing once again as a Task<T>
?
- 最初从WCF Web服务发出, li>
- originally emanating from a WCF webservice but that's not important here
编辑:更具体的说法:
public class TranslatingExceptions
{
public Task ApiAsync() // The inner layer exposes it exactly this way
{
return Task.Factory.StartNew(()=>{ throw new Exception( "Argument Null" );});
}
public Task WrapsApiAsync() // this layer needs to expose it exactly this way
{
// async preview pseudocode for what I need to do
try {
await ApiAsync( );
} catch (Exception exception){
if( exception.Message == "Argument Null" )
throw new ArgumentNullException();
}
}
[Fact]
public void Works()
{
var exception = Record.Exception( () =>
WrapsApiAsync().Wait());
Assert.IsType<ArgumentNullException>( exception.InnerException);
}
}
如何实现 WrapsApiAsync ()
不需要C#5?
How would you implement WrapsApiAsync()
without needing C# 5?
推荐答案
你在寻找什么,这里是所有你需要做的构建在4.0的等效:
Ok, so now that I'm entirely clear on what you're looking for, here's all you would need to do to build the equivalent in 4.0:
public class TranslatingExceptions
{
public Task ApiAsync() // The inner layer exposes it exactly this way
{
return Task.Factory.StartNew(()=>{ throw new Exception( "Argument Null" );});
}
public Task WrapsApiAsync() // this layer needs to expose it exactly this way
{
// Grab the task that performs the "original" work
Task apiAsyncTask = ApiAsync();
// Hook a continuation to that task that will do the exception "translation"
Task result = aspiAsync.ContinueWith(antecedent =>
{
// Check if the antecedent faulted, if so check what the exception's message was
if ( antecedent.IsFaulted
&& antecedent.Exception.InnerException.Message == "Argument Null" )
{
throw new ArgumentNullException();
}
},
TaskContinuationOptions.ExecuteSynchronously);
// Now we return the continuation Task from the wrapper method so that the caller of the wrapper method waits on that
return result;
}
[Fact]
public void Works()
{
var exception = Record.Exception(() =>
WrapsApiAsync().Wait());
Assert.IsType<ArgumentNullException>(exception.InnerException);
}
}
这将完成你要找的东西。需要注意的一点是,在创建延续时,我使用 TaskContinuationOptions.ExecuteSynchronously
。这是因为这项工作是小而紧的,你不想招致一个整个其他线程必须从线程池中拾取的调度程序只是为了做这个检查。
This should accomplish what you're looking for. One thing to note is that I use TaskContinuationOptions.ExecuteSynchronously
when creating the continuation. This is because this work is small and tight and you don't want to incur the over head of waiting for a whole other thread having to be picked up from the thread pool by the scheduler just to do this check.
这篇关于使用任务并行库来翻译void任务的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!