2011-04-04 40 views
2

我嘗試在WCF數據服務中實現'AsyncPattern'。我在界面中定義了兩種方法BeginGetExperiments(...)和EndGetExperiments(...),並實現瞭如下所示的方法。服務器端AsyncPattern調用SQL服務器

public class GmdProfileService : IGmdProfileService 
{ 
IAsyncResult IGmdProfileService.BeginGetExperiments(AsyncCallback callback, object state) 
    { 
     //IAsyncResult res = Experiment.GetExperimentsAsync(callback, state, Properties.Settings.Default.gmdConnectionString); 
     //return res; 

     System.Data.SqlClient.SqlConnectionStringBuilder csb = new System.Data.SqlClient.SqlConnectionStringBuilder(Properties.Settings.Default.gmdConnectionString); 
     csb.AsynchronousProcessing = true; 
     System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(csb.ConnectionString); 
     conn.Open(); 
     System.Data.SqlClient.SqlCommand cmd = conn.CreateCommand(); 
     cmd = conn.CreateCommand(); 
     cmd.CommandText = "SELECT id, name, comment, date, doi FROM tf.TagList WITH(NOLOCK) WHERE proprietary=0;"; 
     cmd.CommandType = System.Data.CommandType.Text; 
     return new SqlCommandAsyncResult(cmd, callback, state); 
    } 

    public List<Experiment> EndGetExperiments(IAsyncResult result) 
    { 
     List<Experiment> res = new List<Experiment>(); 
     SqlCommandAsyncResult myresult = result as SqlCommandAsyncResult; 
     using (System.Data.SqlClient.SqlDataReader reader = myresult.cmd.EndExecuteReader(myresult.originalState as IAsyncResult)) 
     { 
      try 
      { 
       while (reader.Read()) 
       { 
        res.Add(new Experiment(reader)); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
      finally 
      { 
       // Closing the reader also closes the connection, because this reader was created using the CommandBehavior.CloseConnection value. 
       if (reader != null) 
       { 
        reader.Close(); 
       } 
      } 
     } 
     return res; 
    } 

BeginGetExperiments返回類SqlCommandAsyncResult實現在另外IAsyncResult接口持有後來訪問我SqlCommand參考。

public class SqlCommandAsyncResult : IAsyncResult 
{ 
    public SqlCommand cmd { get; private set; } 
    public IAsyncResult originalState { get; private set; } 

    public SqlCommandAsyncResult(SqlCommand cmd, AsyncCallback callback, object state) 
    { 
     this.cmd = cmd; 
     this.originalState = cmd.BeginExecuteReader(callback, 
      state, 
      System.Data.CommandBehavior.SequentialAccess | // doesn't load whole column into memory 
      System.Data.CommandBehavior.CloseConnection // close connection immediately after read 
      ); 
    } 

    public object AsyncState 
    { 
     get { return originalState.AsyncState; } 
    } 

    public WaitHandle AsyncWaitHandle 
    { 
     get { return originalState.AsyncWaitHandle; } 
    } 

    public bool CompletedSynchronously 
    { 
     get { return false; } 
    } 

    public bool IsCompleted 
    { 
     get { return AsyncWaitHandle.WaitOne(0); } 
    } 
} 

我面臨的困難是在EndGetExperiments方法。我不知道如何訪問SqlCommand致電EndExecuteReader(...)。 通常我會使用BeginExecutereader中的狀態對象來傳遞命令。但是,如果我這樣做,我會得到以下例外: 「IAsyncResult的狀態必須是傳遞給您的Begin調用的狀態參數。」

所以我嘗試使用IAsyncResult將SqlCommand傳遞給EndGetExperiments。這裏,我不明白的是,在EndGetExperiments中,可變結果是類型IAsyncResult或類型SqlCommandAsyncResult,具體取決於SqlCommandAsyncResult類中的CompletedSynchronously的值。 設置CompletedSynchronously = false使我的代碼失敗,因爲我不能訪問SqlCommand,而設置CompletedSynchronously = true代碼的作品就像一個魅力,但我有一種奇怪的感覺,可能會出現問題。

感謝任何幫助,指導和示例代碼如何使這個代碼工作,甚至更重要的是幫助我瞭解手頭的問題。

非常感謝。 Jan

回答

1

如果您使用的是C#4.0。這可能更容易使用Task<T>來實現。 Task<T>將執行Func<T>其中T是返回值。您可以定義一個獲取Parent.Result的延續任務。我知道這個答案可能不是你要找的。但請考慮將此作爲替代方案。代碼將更清潔,易於維護並且易於調試(使用任務並行窗口,並行堆棧等)。

+0

感謝@tonyjy的輸入,但是您的建議模式與'[OperationContractAttribute(...)中的BeginMyMethod(...)EndMyMethod(...) AsyncPattern = true)]'wcf數據服務? – jahu 2011-04-04 13:38:47

+0

我想這取決於你想達到的目標。如果您正在嘗試實現您的客戶端在調用WCF時不阻塞地運行。服務器可以實現爲同步,客戶端可以使用異步。任務將在客戶端非常有用,無論是TreadPool還是ConcurrentContext。 – tonyjy 2011-04-04 14:36:33

+0

再次感謝。我很困惑。我上面發佈的代碼顯然在服務器端運行。我試圖弄清楚的是,如何使用最佳實踐技術來實現wcf數據服務的**服務器端**,以便從SQl服務器獲取一些數據,然後將它們轉發給客戶端。我試着按照這裏提供的'AsyncPattern = true':[link](http://msdn.microsoft.com/en-us/library/ms731177.aspx)。到目前爲止,我只是在談論服務器端。 – jahu 2011-04-04 14:51:21