从WCF服务调用基于任务的异步单向回调方法

我有一个WCF服务,它使用回调合同来通知客户端,类似于此

public interface IClientCallback { [OperationContract(IsOneWay = true)] void NotifySomething(); } 

和调用它的服务代码类似于此

 void NotifySomething() { try { this.callback.NotifySomething(); } catch (Exception ex) { // Log the exception and eat it } } 

请注意,根据设计,回调通知是可选的 ,即很好,但不是必需的。 这就是为什么它被标记为OneWay并且实现吃exception。

由于一些误解,我们认为这对于拥有一个非阻塞的火灾和忘记方法就足够了。 但当然这不是真的,所以在某些情况下它会阻塞一段时间,这会导致问题,因为它是从内部线程同步块调用的。 因此,我们决定通过更改定义使其异步,如下所示

 public interface IClientCallback { [OperationContract(IsOneWay = true)] Task NotifySomething(); } 

我对客户端实现没有问题,我的问题是如何从服务中调用它。 这是我正在考虑的事情

 async void NotifySomething() { try { await this.callback.NotifySomething(); } catch (AggregateException ex) { // Unwrap, log the exception(s) and eat it } catch (Exception ex) { // Log the exception and eat it } } 

现在,既然每个人都说async void不是一个好习惯,可以在这里使用它吗? 我还有其他选择吗? 在WCF服务上下文中执行此操作的建议方法是什么?

你编写它的方式非常安全,因为它处理exception。 您还可以编写可重用的扩展方法来执行此操作,以便您不需要重复它。

也许是这样的:

 public static class Extensions { public static void FireAndForget(this Task task) { task.ContinueWith(t => { // log exceptions t.Exception.Handle((ex) => { Console.WriteLine(ex.Message); return true; }); }, TaskContinuationOptions.OnlyOnFaulted); } } public async Task FailingOperation() { await Task.Delay(2000); throw new Exception("Error"); } void Main() { FailingOperation().FireAndForget(); Console.ReadLine(); }