Search code examples
wcfchannelfactory

WCF - How to hold on to the Channel/Proxy between Begin and End call


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.


Solution

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

    }