【问题标题】:Error when I use the Task-based Asynchronous Pattern in the client of duplex WCF service在双工 WCF 服务的客户端中使用基于任务的异步模式时出错
【发布时间】: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 毫无意义,只会降低性能。

标签: c# wpf wcf


【解决方案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 不可能
猜你喜欢
  • 1970-01-01
  • 2012-12-17
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多