2011-03-29 67 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

相關問題