WCF - Как удерживать канал / прокси между началом и завершением вызова - PullRequest
3 голосов
/ 29 марта 2011

Я пытаюсь использовать ChannelFactory для вызова асинхронной службы.

Бит, в котором я не уверен, - как лучше удерживать ссылку на канал - между вызовом BeginSave и затемEndSave (который находится в методе обратного вызова).

В настоящее время я делаю это, присваивая его переменной экземпляра, но это не кажется идеальным.Я только хочу, чтобы канал существовал в течение всего времени вызова (что я считаю лучшей практикой, т. Е. Открыть, использовать его, закрыть его).Я также хочу убедиться, что закрываю правильный канал, могут быть ситуации, когда существует более одного канала.

Любые примеры того, как лучше всего это сделать, были бы великолепны.

Вот мой код:

public partial class MyForm : Form
{

    ICompanyService m_Channel;

    public MyForm()
    {
        InitializeComponent();

    // ChannelProvider is a class I've created which returns a channel created by the ChannelFactory
        ChannelProvider<ICompanyService> channelProvider = new ChannelProvider<ICompanyService>();
        m_Channel = channelProvider.GetChannel();
    }

    private void OnSaveButtonClickAsync(object sender, EventArgs e)
    {
        Company company = new Company();
        company.BranchId = "A1";
        company.CompanyName = "A1 LTD";

        m_Channel.BeginSave(
            company, 
            new AsyncCallback(OnSaveCallback), 
            null);

        StatusLabel.Text = "Saving...";
    }

    private void OnSaveCallback(IAsyncResult ar)
    {
        int result = m_Channel.EndSave(ar);

        Invoke(
            new MethodInvoker(delegate()
            {
               StatusLabel.Text = result.ToString(); 
            }));
    }
}

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 04 апреля 2011

Я нашел ответ на этот вопрос в книге WCF Ювала Лоуи.Используя мой оригинальный пример, это можно переписать следующим образом:

открытый частичный класс MyForm: Форма {

public MyForm()
{
    InitializeComponent();
}

private void OnSaveButtonClickAsync(object sender, EventArgs e)
{
    Company company = new Company();
    company.BranchId = "A1";
    company.CompanyName = "A1 LTD";

    // ChannelProvider is a class I've created which returns a channel created by the ChannelFactory
    ChannelProvider<ICompanyService> channelProvider = new ChannelProvider<ICompanyService>();
    channel = channelProvider.GetChannel();

    channel.BeginSave(
        company, 
        new AsyncCallback(OnSaveCallback), 
        channel);

    StatusLabel.Text = "Saving...";
}

private void OnSaveCallback(IAsyncResult ar)
{
    int result = m_Channel.EndSave(ar);

    IContextChannel contextChannel = (IContextChannel)ar.AsyncState;
    contextChannel.Close();

    Invoke(
        new MethodInvoker(delegate()
        {
           StatusLabel.Text = result.ToString(); 
        }));
}

}

0 голосов
/ 01 апреля 2011


извините за задержку с вами.Одна из проблем, которые, я думаю, у вас есть, заключается в том, что вы неправильно создаете экземпляр своего прокси.Не уверен, что вы делаете channelprovider, но создание собственного канала довольно просто и может не нуждаться в оболочке.

Я попробовал простой тест, используя старый пример сервиса калькулятора, и обнаружил, что у меня нет проблем с сохранением открытого канала.

Сначала я создал два поля ...

    private ChannelFactory<ICalculator> m_Factory;
    private ICalculator m_Proxy;

Затем создал экземпляр фабрики в конструкторе, используя конфигурацию клиента в файле конфигурации.

    m_Factory = new ChannelFactory<ICalculator>("calc");

Затем, когдавызывая сервис, я создаю свой прокси и выполняю асинхронный метод.Как только вызов возвращен, я преобразовываю прокси в объект ICommunicationObject, который сообщает мне состояние моего канала.Вы должны увидеть, что вызванный вами прокси-сервер все еще открыт.После этого вы сможете закрыть его.

    void OnBegin(object sender, EventArgs e)
    {
        m_Proxy = m_Factory.CreateChannel();
        m_Proxy.BeginAdd(2, 3, OnCompletion, null);

        // Do other stuff...
    }

    void OnCompletion(IAsyncResult result)
    {
        int sum = m_Proxy.EndAdd(result);
        result.AsyncWaitHandle.Close();

        ICommunicationObject channel = (ICommunicationObject)m_Proxy;
        if (channel.State == CommunicationState.Opened)
            channel.Close();
    }

Надеюсь, это поможет.

...