在双工 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 方法应返回 Task 或 Task 。 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 服务的客户端中使用基于任务的异步模式时出错的主要内容,如果未能解决你的问题,请参考以下文章