2011-03-29 53 views
3

我正在尝试使用ChannelFactory来调用异步服务。WCF - 如何保持开始和结束通话之间的通道/代理

我不确定的一点是如何最好地保持对通道的引用 - 在调用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(); 
      })); 
    } 
} 

非常感谢。

+0

只是出于好奇,为什么你要守住通道?你想用它来打另一个电话吗?我不明白你在做什么。 – stephenl 2011-03-31 05:57:31

+0

这样我可以调用服务的EndSave方法,然后关闭OnSaveCallback方法中的通道。例如,如果我正在同步调用,则可以在同一个方法中完成所有这些操作,而无需实例/成员变量。 – P2l 2011-03-31 12:37:28

回答

0

我在Juval Lowy的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


对此感到遗憾。我认为你的问题之一是你没有正确地实例化你的代理。不确定你的频道提供者做什么,但创建你自己的频道非常简单,可能不需要包装。

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

首先,我创建了两个领域...

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

希望这会有所帮助。

+0

嗨,史蒂夫,谢谢你花时间在这里帮忙。我之后真正的做法是在不使用成员/实例变量的情况下保持对begin和end调用之间的代理的引用。重读Juval Lowy书后,我想我现在已经找到了这个。我会尽快发布一个完整的解释。 – P2l 2011-04-04 13:32:54

相关问题