WCF - 如何在开始和结束调用之间保留通道/代理

发布于 2024-10-27 13:15:58 字数 1301 浏览 3 评论 0原文

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

非常感谢。

I'm attempting to use the ChannelFactory to call an asynchronous service.

The bit I'm unsure of is how to best hold on to the reference to the channel - between the call to BeginSave and then EndSave (which is in the callback method).

I'm currently doing this by assigning it to an instance variable, but this doesn't seem ideal. I only want the channel to exist for the lifetime of the call (which I think is best practice i.e. Open, use it, close it). I also want to make sure I'm closing the correct channel, there could be situations where there's more than one in existence.

Any examples on how best to do this would be great.

Here's my code:

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

Many thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一笔一画续写前缘 2024-11-03 13:15:58

很抱歉延迟回复您此事。我认为您遇到的问题之一是您没有正确实例化代理。不确定您的频道提供商做什么,但创建您自己的频道非常简单,可能不需要包装器。

我使用旧的计算器服务示例尝试了一个简单的测试,发现保持通道开放没有任何困难。

首先,我创建了两个字段...

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

希望这有帮助。

sorry about the delay in getting back to you on this. One of the problems I think you have is that you are not instantiating your proxy correctly. Not sure what you channelprovider does but creating you own channel is pretty straight forward and might not need a wrapper.

I tried a simple test using the old calculator service sample and found I had no difficulties with keeping the channel open.

First I created two fields...

    private ChannelFactory<ICalculator> m_Factory;
    private ICalculator m_Proxy;

Then instantiated the factory in the constructor using the client config in the config file.

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

Then when invoking the service I create my proxy and execute the async method. Once the call is returned I convert the proxy into a ICommunicationObject which gives me the state of my channel. You should see that the proxy you invoked is still open. You should then be able to close it.

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

Hope this helps.

温暖的光 2024-11-03 13:15:58

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

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

}

I found the answer to this in Juval Lowy's WCF book. Using my original example, this can be rewritten as follows:

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

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文