将 WCF Web 服务调用从基于回调的异步方法转换为等待任务
Converting WCF Web service calls from callback-based async method to awaitable task
我正在将使用基于回调的 WCF Web 服务的旧 Silverlight 应用程序转换为使用基于可等待任务的 WCF Web 服务的 OpenSilver。我想弄清楚如何处理错误情况。这是基于回调的代码:
private void GetNextImage()
{
var cmc = ServiceFactories.CreateCartManager();
cmc.getSlideImageCompleted += (s, e) =>
{
cmc_getSlideImageCompleted(s, e);
};
var lastTime = SystemSettings.GetInstance().SlideShowData.LastImageTime;
cmc.getSlideImageAsync(string.IsNullOrEmpty(lastTime) ? null : lastTime);
}
void cmc_getSlideImageCompleted(object sender, getSlideImageCompletedEventArgs e)
{
if (e.Cancelled)
{
GetNextImage();
}
else if (e.Error != null)
{
var errMsg = new ErrorWindow("Error while trying to get next image in slide show:", msg);
errMsg.Show();
}
else if (e.Result == null)
{
// There are no images in the slide show right now.
}
else
{
// we have an image!!!!
var imageData = e.Result.imageData;
// <the rest of the code>
}
}
我知道 GetNextImage() 应该是这样的:
private async Task GetNextImage()
{
var cmc = ServiceFactories.CreateCartManager();
var lastTime = SystemSettings.GetInstance().SlideShowData.LastImageTime;
var result = await cmc.getSlideImageAsync(string.IsNullOrEmpty(lastTime) ? null : lastTime);
cmc_getSlideImageCompleted(result);
}
void cmc_getSlideImageCompleted(getSlideImageResponse e)
{
...
}
问题是,e.Cancelled、e.Error、e.Result发生了什么?我现在如何解释较低级别的错误?
What happened to e.Cancelled, e.Error, and e.Result?
e.Cancelled
如果您有异步方法(在您的情况下为 cmc.getSlideImageAsync
),则可以通过 CancellationToken
取消。在此方法中,如果您反复检查请求取消的位置(通过 ThrowIfCancellationRequested
),那么它将抛出一个 OperationCanceledException
(或派生的 class)。
所以,e.Cancelled
的等价物是这样的:
getSlideImageResponse response;
try
{
response = await cmc.getSlideImageAsync(..., cancellationToken);
}
catch(OperationCanceledException ex)
{
//if(e.Cancelled) logic goes here
}
e.Error
如果您的异步方法因任何原因失败,那么它将填充底层 Task
的 Exception
属性.
Task<getSlideImageResponse> getTask = cmc.getSlideImageAsync(...);
getTask.Wait(); //BAD PRACTICE, JUST FOR DEMONSTRATION PURPOSES
if(getTask.Exception != null)
{
//if(e.Error != null) logic goes here
}
上面的代码不是最理想的,因为 .Wait
是一个阻塞调用,可能会导致死锁。推荐的方法是使用 await
。此运算符可以从 Task
中检索 .Exception
属性 并可以再次抛出它:
getSlideImageResponse response;
try
{
response = await cmc.getSlideImageAsync(...);
}
catch(Exception ex)
{
//if(e.Error != null) logic goes here
}
e.Result
此 属性 仅在方法未取消或未失败时才会填充。这里也是一样:
getSlideImageResponse response;
try
{
response = await cmc.getSlideImageAsync(..., cancellationToken);
}
catch(OperationCanceledException ocex)
{
//if(e.Cancelled) logic goes here
}
catch(Exception ex)
{
//if(e.Error != null) logic goes here
}
//if(e.Result != null) logic goes here
我正在将使用基于回调的 WCF Web 服务的旧 Silverlight 应用程序转换为使用基于可等待任务的 WCF Web 服务的 OpenSilver。我想弄清楚如何处理错误情况。这是基于回调的代码:
private void GetNextImage()
{
var cmc = ServiceFactories.CreateCartManager();
cmc.getSlideImageCompleted += (s, e) =>
{
cmc_getSlideImageCompleted(s, e);
};
var lastTime = SystemSettings.GetInstance().SlideShowData.LastImageTime;
cmc.getSlideImageAsync(string.IsNullOrEmpty(lastTime) ? null : lastTime);
}
void cmc_getSlideImageCompleted(object sender, getSlideImageCompletedEventArgs e)
{
if (e.Cancelled)
{
GetNextImage();
}
else if (e.Error != null)
{
var errMsg = new ErrorWindow("Error while trying to get next image in slide show:", msg);
errMsg.Show();
}
else if (e.Result == null)
{
// There are no images in the slide show right now.
}
else
{
// we have an image!!!!
var imageData = e.Result.imageData;
// <the rest of the code>
}
}
我知道 GetNextImage() 应该是这样的:
private async Task GetNextImage()
{
var cmc = ServiceFactories.CreateCartManager();
var lastTime = SystemSettings.GetInstance().SlideShowData.LastImageTime;
var result = await cmc.getSlideImageAsync(string.IsNullOrEmpty(lastTime) ? null : lastTime);
cmc_getSlideImageCompleted(result);
}
void cmc_getSlideImageCompleted(getSlideImageResponse e)
{
...
}
问题是,e.Cancelled、e.Error、e.Result发生了什么?我现在如何解释较低级别的错误?
What happened to e.Cancelled, e.Error, and e.Result?
e.Cancelled
如果您有异步方法(在您的情况下为 cmc.getSlideImageAsync
),则可以通过 CancellationToken
取消。在此方法中,如果您反复检查请求取消的位置(通过 ThrowIfCancellationRequested
),那么它将抛出一个 OperationCanceledException
(或派生的 class)。
所以,e.Cancelled
的等价物是这样的:
getSlideImageResponse response;
try
{
response = await cmc.getSlideImageAsync(..., cancellationToken);
}
catch(OperationCanceledException ex)
{
//if(e.Cancelled) logic goes here
}
e.Error
如果您的异步方法因任何原因失败,那么它将填充底层 Task
的 Exception
属性.
Task<getSlideImageResponse> getTask = cmc.getSlideImageAsync(...);
getTask.Wait(); //BAD PRACTICE, JUST FOR DEMONSTRATION PURPOSES
if(getTask.Exception != null)
{
//if(e.Error != null) logic goes here
}
上面的代码不是最理想的,因为 .Wait
是一个阻塞调用,可能会导致死锁。推荐的方法是使用 await
。此运算符可以从 Task
中检索 .Exception
属性 并可以再次抛出它:
getSlideImageResponse response;
try
{
response = await cmc.getSlideImageAsync(...);
}
catch(Exception ex)
{
//if(e.Error != null) logic goes here
}
e.Result
此 属性 仅在方法未取消或未失败时才会填充。这里也是一样:
getSlideImageResponse response;
try
{
response = await cmc.getSlideImageAsync(..., cancellationToken);
}
catch(OperationCanceledException ocex)
{
//if(e.Cancelled) logic goes here
}
catch(Exception ex)
{
//if(e.Error != null) logic goes here
}
//if(e.Result != null) logic goes here