【问题标题】:Call synchronous WCF operation contract methods asynchronously on silverlight在 silverlight 上异步调用同步 WCF 操作协定方法
【发布时间】:2011-11-30 16:27:58
【问题描述】:

我们通过使用 ChanellFacotry 创建代理,在 silverlight 应用程序上使用 wcf 服务。

Operation 和 Data 合约暴露给 silverlight trough 组件,该组件由来自服务器端 Data 和 Operation 合约库的共享文件组成。 (天哪,我希望你明白我在说什么)。

所以服务器和客户端使用相同的操作和数据契约。

Silverlight wcf 客户端库有一个限制,不能同步调用 wcf 方法,如您所知,因此共享操作合同文件必须公开每个操作的异步版本。

如果它们不包含阻塞操作,编写异步 WCF 服务将是有意义的,但是当我们使用 EF 时,异步是通过将阻塞工作委托给线程池来实现的。无论如何,这就是 WCF 为同步方法所做的。而这个事实让我想撕掉我的眼睛(#@%!^%!@%)。

我们的项目顾问有权不允许在客户端生成动态代理来调用同步操作合约方法(如果您有兴趣,请谷歌 Yevhen Bobrov Servelat Pieces)。所以我们必须在服务器端编写异步方法的有意识的实现,而没有任何性能提升(你记得阻塞调用)。

是否可以使用 Silverlight 的数据契约从 Silverlight 调用 wcf Web 服务同步方法?

你以前有没有遇到过这个问题,如果有,你是怎么解决的?

目前,我期待仅使用服务器端合约作为转换源为客户端生成异步合约。也许有一些 t4 模板可以很好地为我做到这一点?

对不起,文字墙,只是为了混合一些代码来回答我的问题,这就是异步合约实现现在的样子:

    /// <summary>
    /// Subscribes to users of the specified organization.
    /// </summary>
    /// <param name="organizationId">The organization id.</param>
    public void Unsubscribe(int organizationId)
    {
        var clientId = this.OperationContext.GetClientId();
        if (string.IsNullOrEmpty(clientId))
        {
            return;
        }

        this.InternalUnsubscribe(organizationId, clientId);
    }

    /// <summary>
    /// Begins an asynchronous operation to Unsubscribe.
    /// </summary>
    /// <param name="organizationId">The organization id.</param>
    /// <param name="callback">The callback.</param>
    /// <param name="passThroughData">The pass through data.</param>
    /// <returns>
    /// An implementation of <see cref="IAsyncResult"/> that provides access to the state or result of the operation.
    /// </returns>
    public IAsyncResult BeginUnsubscribe(int organizationId, AsyncCallback callback, object passThroughData)
    {
        var clientId = this.OperationContext.GetClientId();
        if (string.IsNullOrEmpty(clientId))
        {
            return null;
        }

        var asyncResult = new VoidAsyncResult(callback, passThroughData);
        Task.Factory.StartNew(() =>
            {
                try
                {
                    this.InternalUnsubscribe(organizationId, clientId);
                    asyncResult.SetAsCompleted(false);
                }
                catch (Exception ex)
                {
                    asyncResult.SetAsCompleted(ex, false);
                }
            });
        return asyncResult;
    }

    /// <summary>
    /// Ends an existing asynchronous operation to Unsubscribe.
    /// </summary>
    /// <param name="result">The <see cref="IAsyncResult"/> provided by the BeginUnsubscribe operation.</param>
    public void EndUnsubscribe(IAsyncResult result)
    {
        var response = result as VoidAsyncResult;
        if (response != null)
        {
            response.EndInvoke();
        }
    }

【问题讨论】:

    标签: .net silverlight wcf asynchronous


    【解决方案1】:

    您无需将 WCF 服务编写为异步的。您只需为定义 Async 方法的服务创建一个 ServiceContract。这是一个简单的例子

    [ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        int Foo(string input);
    }
    
    //tell wcf that this contract applies to IMyService
    [ServiceContract(Name = "IMyService")]
    public interface IMyServiceAsync
    {
        //setting AsyncPattern = true allows WCF to map the async methods to the sync ones.
        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginFoo(string input, AsyncCallback callback, object asyncState);
    
        int EndFoo(IAsyncResult result};
    }
    
    // you only need to implement the sync contract
    public class MyService : IMyService
    {
        public int Foo(string input)
        {
            return input.Length;
        }
    }
    

    现在将 IMyServiceAsync 与您的 ChannelFactory 一起使用,一切都会正常工作。

    【讨论】:

    • 谢谢,我刚刚找到了一个可以做这个转换的t4模板,现在试试。
    • 让我知道它是如何工作的。我一直想找 t4 来做这件事,但一直没有时间。
    • 失败,将尝试显式指定操作名称
    • 不,我有这个想法,但它只是不想在服务上调用同步方法。
    • @Mas 我刚刚在我的示例中看到了一个错字。现在我已经修复它应该可以工作了。
    猜你喜欢
    • 2013-10-26
    • 1970-01-01
    • 2016-04-07
    • 2016-06-21
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多