在silverlight上异步调用同步WCF操作契约方法

时间:2011-10-04 12:57:20

标签: .net silverlight wcf asynchronous

我们正在使用ChanellFacotry通过创建代理来使用Silverlight应用程序上的wcf服务。

操作和数据合同暴露于silverlight槽组件,该组件由来自服务器端数据和操作合同库的共享文件组成。 (我希望你明白我在说什么)。

因此服务器和客户端使用相同的操作和数据合同。

Silverlight wcf客户端lib有一个限制,就是无法同步调用wcf方法,因此共享操作契约文件必须公开每个操作的asyn版本。

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

我们的项目顾问有权不允许在客户端生成动态代理以调用同步操作合同方法(如果您感兴趣,可以使用google Yevhen Bobrov Servelat Pieces)。因此,我们必须在服务器端编写异步方法的senseles实现,而不会产生任何性能提升(在您记忆时阻止调用)。

是否可以使用其数据合约从silverlight调用wcf web service同步方法?

你以前遇到过这个问题,如果是这样,你是如何解决的?

我很期待只使用服务器端合同作为转换源为客户端生成异步合同。也许有一些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();
        }
    }

1 个答案:

答案 0 :(得分:3)

您无需将WCF服务编写为Async。您只需要为定义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;
    }
}

现在在你的ChannelFactory上使用IMyServiceAsync,一切都应该有效。