在双工 WCF 服务的客户端中使用基于任务的异步模式时出错

Posted

技术标签:

【中文标题】在双工 WCF 服务的客户端中使用基于任务的异步模式时出错【英文标题】:Error when I use the Task-based Asynchronous Pattern in the client of duplex WCF service 【发布时间】:2014-08-27 00:27:35 【问题描述】:

我开发的下载管理器应用程序由两部分组成: 1) Duplex WCF 服务执行下载并将下载状态数据实时发送到客户端。 2) WPF 客户端从服务接收下载状态数据并显示在 DataGrid 中。在我的双工WCF服务中有一个回调接口

 [ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))] 
 public interface IDownloadManagerServiceCalback
 
     /// <summary>
     /// Returns changed downloading status to client.
     /// </summary>
     /// <returns>Downloading which has changed status</returns>
     [OperationContract(IsOneWay = true)]
     void UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
 

在客户端我实现了这个接口:

 class CallbackHandler : IDownloadManagerServiceCallback
 
     /// <summary>
     /// "Download status changed" event.
     /// </summary>
     public event EventHandler<DownloadStatusChangedEventArgs> DownloadStatusChanged;

     public async Task UpdateSelectedDownload(DownloadStatus p_UpdatedDownload)
     
         await Task.Run(() =>
         
             // If handler was subscribed to event:
             if (DownloadStatusChanged != null)
             
                  DownloadStatus updatedDownload = p_UpdatedDownload;
                  DownloadStatusChangedEventArgs updatedDownloadArgs = new DownloadStatusChangedEventArgs();
                  updatedDownloadArgs.Download = updatedDownload;
                  DownloadStatusChanged(this, updatedDownloadArgs);
             
         );
    
 

当我构建解决方案时,出现以下错误(我将错误消息的文本从俄语翻译成英语,因为我的 Visual Studio 2013 是俄语化的):

DownloadManager_Client.CallbackHandler 没有实现成员“DownloadManager_Client.DownloadManager_ServiceReference.IDownloadManagerServiceCallback.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)”。 “DownloadManager_Client.CallbackHandler.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)”无法实现“DownloadManager_Client.DownloadManager_ServiceReference.IDownloadManagerServiceCallback.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)”,因为它不包含适当的返回“void”类型。

这里DownloadManager_Client是WPF客户端项目的名称,DownloadManager_ServiceReference是客户端项目中WCF服务的服务引用名称。我该如何纠正这个错误?

【问题讨论】:

您不需要在客户端和服务器上使用相同的接口。您可以在服务器上拥有一个没有 Task 的接口,而在客户端上拥有一个与 Task 兼容的接口定义。 另外,您使用 async 毫无意义,只会降低性能。 【参考方案1】:

接口应定义为返回 Task 而不是 void,因为您的实现是一个返回 Task异步方法 >.

编辑:您处于泡菜状态,因为您想使用需要返回 Task 的异步,但是您的方法被标记为 IsOneWay = true - 您不能同时拥有两者。 IsOneWay = false 并保持异步性质或保持单向但删除异步。

示例 1 - 异步方法

 [ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))] 
 public interface IDownloadManagerServiceCalback
 
     /// <summary>
     /// Returns changed downloading status to client.
     /// </summary>
     /// <returns>Downloading which has changed status</returns>
     [OperationContract(IsOneWay = false)]
     Task UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
 

然后保持你原来的实现返回任务

示例 2 - 单向方法

 [ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))] 
 public interface IDownloadManagerServiceCalback
 
     /// <summary>
     /// Returns changed downloading status to client.
     /// </summary>
     /// <returns>Downloading which has changed status</returns>
     [OperationContract(IsOneWay = true)]
     void UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
 

在您的实现中删除任何等待;异步;任务。

一般

异步 ​​WCF 方法应返回 TaskTask async void 的唯一时间是在 事件处理程序 期间,这在此处不适用。

作为异步方法的一般规则 - 避免 async void 就像瘟疫一样,因为 在 try catch 中抛出异常这种方法不能被常规的 try-catch 捕获。唯一的例外(没有双关语是在事件处理程序期间)。

Async void 方法具有不同的错误处理语义。当异步任务或异步任务方法抛出异常时,会捕获该异常并将其放置在任务对象上。对于 async void 方法,没有 Task 对象,因此任何从 async void 方法抛出的异常都将直接在 async void 方法启动时处于活动状态的 SynchronizationContext 上引发。 More...

您想了解更多吗?

Best Practices in Asynchronous Programming

【讨论】:

我更正了方法,现在看起来像这样:[OperationContract(IsOneWay = true)] Task UpdateSelectedDownload(DownloadStatus p_SelectedDownload);但错误仍然存​​在。你的建议没有帮助。 啊,那是因为它是 一种方式,它对 WCF 说“我不关心返回响应”。根据您的意图,我认为您应该删除方法的异步性。从 WCF 的角度来看,我同意您的“回调”应该是单向的 我需要 UpdateSelectedDownload 方法在客户端异步执行。 @user3769902 不可能

以上是关于在双工 WCF 服务的客户端中使用基于任务的异步模式时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何在 azure wcf 中继中处理双工 wcf

如果出现故障,如何自动重新建立双工通道?

请求-响应与双工 WCF 消息交换模式

在 WCF 双工合同中检测客户端死亡

异步调用 WCF 服务并在新任务中等待它

响应式 WCF 客户端的双工回调或客户端线程