Вызовите методы контракта синхронной операции WCF асинхронно на silverlight - PullRequest
5 голосов
/ 04 октября 2011

Мы используем службы wcf в приложении silverlight, создавая прокси с помощью ChanellFacotry.

Контракты «Операция» и «Данные» подвергаются сквозной сборке silverlight, которая состоит из общих файлов из серверной библиотеки «Контракты о данных и операциях». (О боже, я надеюсь, вы понимаете, о чем я говорю).

Таким образом, сервер и клиент используют одинаковые операции и контракты данных.

Silverlight wcf клиент lib имеет ограничение на невозможность синхронного вызова методов wcf, как вы знаете, поэтому файл контракта с общей операцией должен предоставлять асиновые версии каждой операции.

Написание асинхронной службы WCF имело бы некоторый смысл, если бы в ней не было операций блокировки, но, поскольку мы используем EF, асинхронность достигается путем делегирования блокирующей работы пулу потоков. Это то, что WCF делает для методов синхронизации в любом случае. И этот факт заставляет меня хотеть оторвать глаза (# @%! ^%! @%).

Наш консультант проекта может запретить генерировать динамические прокси на клиенте для вызова методов контракта операции синхронизации (google, Евгений Бобров, Части сервелата, если вам интересно). Поэтому мы должны написать бессмысленные реализации асинхронных методов на стороне сервера без какого-либо увеличения производительности (блокировка вызовов, как вы помните).

Можно ли вызвать синхронный метод веб-службы wcf из silverlight, используя контракт данных?

Вы когда-нибудь сталкивались с этой проблемой раньше? Если да, то как вы ее решили?

В данный момент я с нетерпением жду возможности создания асинхронных контрактов для клиентской стороны, используя только серверные контракты в качестве источника преобразования. Может быть, есть какой-нибудь шаблон 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 Ответ

3 голосов
/ 04 октября 2011

Вам не нужно писать службу WCF, чтобы она была асинхронной. Вам просто нужно создать ServiceContract для вашего сервиса, который определяет методы Async. Вот быстрый пример

[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, и все должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...