简体   繁体   English

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

[英]Calling a task-based asynchronous one way callback method from WCF service

I have a WCF service which uses a callback contract to notify the clients, similar to this 我有一个WCF服务,它使用回调协定来通知客户端,类似于此

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

and the service code calling it similar to this 和调用它的服务代码与此类似

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

Note that by design the callback notification is optional , ie nice to have, but not required. 请注意,根据设计,回调通知是可选的 ,即很高兴,但不是必需的。 That's why it's marked as OneWay and the implementation eats exceptions. 这就是为什么将其标记为OneWay ,并且实现吃掉异常的原因。

Due to some misunderstanding we were thinking that would be enough for having a non blocking fire and forget method. 由于某些误解,我们认为采用非阻塞性的“忘却”方法就足够了。 But of course that wasn't true, so under some circumstances it's blocking for a while, which is causing problems because it's called from inside thread synchronized block. 但是当然那不是真的,因此在某些情况下它会阻塞一段时间,这会引起问题,因为它是从内部线程同步块中调用的。 So we decided to make it asynchronous by changing the definition as follows 因此我们决定通过如下更改定义使其异步

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

I have no problem with client implementation, my question is how to call it from the service. 我对客户端实现没有问题,我的问题是如何从服务中调用它。 Here is what I'm thinking to do 这是我想做的

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
    }
}

Now, since everyone is saying async void is not a good practice, is it ok to use it here? 现在,既然每个人都说async void不是一个好习惯,那么可以在这里使用它吗? What other options do I have? 我还有什么其他选择? What is the recommended way to perform this in the WCF service context? 在WCF服务上下文中执行此操作的推荐方法是什么?

The way you have written it is pretty safe as it handles the exceptions. 您编写的方式非常安全,因为它可以处理异常。 You could also write a reusable extension method to do that so that you don't need to repeat it. 您也可以编写一个可重用的扩展方法来做到这一点,这样就无需重复它。

Perhaps something like this: 也许是这样的:

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM