Асинхронный вызов синхронных методов контракта операции WCF в silverlight

#.net #silverlight #wcf #asynchronous

#.net #silverlight #wcf #асинхронный

Вопрос:

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

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

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

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

Написание асинхронной службы 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 asyncResu<
    }

    /// <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 VoidAsyncResu<
        if (response != null)
        {
            response.EndInvoke();
        }
    }
  

Ответ №1:

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

Комментарии:

1. Спасибо, я только что нашел шаблон t4, который может выполнять это преобразование, и сейчас пытаюсь его выполнить.

2. Дайте мне знать, как это работает. Я собирался искать t4 для этого, но у меня не было времени.

3. При сбое будет предпринята попытка явно указать имя операции

4. нет, у меня есть идея, но он просто не хочет вызывать метод синхронизации в службе.

5. @Mas Я только что увидел опечатку в моем примере. Теперь, когда я это исправил, это должно сработать.