3

我正在尝试使用 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(); 
            }));
    }
}

非常感谢。

4

2 回答 2

0

我在 Juval Lowy 的 WCF 书中找到了答案。使用我原来的例子,这可以重写如下:

公共部分类 MyForm : Form {

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(); 
        }));
}

}

于 2011-04-04T18:00:41.580 回答
0


很抱歉延迟回复您。我认为您遇到的问题之一是您没有正确实例化您的代理。不确定您的 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();
    }

希望这可以帮助。

于 2011-04-01T09:53:25.900 回答