2013-06-11 18 views
0

我有一個Windows應用程序使用SqlDependency在分離的線程池上運行,此應用程序表示日誌監視器UI獲取添加到數據庫中特定表中的最新行並在DataGridView中查看它。你可以看到這個LINK的應用程序源代碼,或者按照這個腳本。不穩定的應用程序使用SqlDependency。幾個狀態和錯誤

const string tableName = "OutgoingLog"; 
    const string statusMessage = "{0} changes have occurred."; 
    int changeCount = 0; 

    private static DataSet dataToWatch = null; 
    private static SqlConnection connection = null; 
    private static SqlCommand command = null; 

    public frmMain() 
    { 
     InitializeComponent(); 
    } 

    private bool CanRequestNotifications() 
    { 
     // In order to use the callback feature of the 
     // SqlDependency, the application must have 
     // the SqlClientPermission permission. 
     try 
     { 
      SqlClientPermission perm = new SqlClientPermission(PermissionState.Unrestricted); 

      perm.Demand(); 

      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    private void dependency_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
     // This event will occur on a thread pool thread. 
     // Updating the UI from a worker thread is not permitted. 
     // The following code checks to see if it is safe to 
     // update the UI. 
     ISynchronizeInvoke i = (ISynchronizeInvoke)this; 

     // If InvokeRequired returns True, the code 
     // is executing on a worker thread. 
     if (i.InvokeRequired) 
     { 
      // Create a delegate to perform the thread switch. 
      OnChangeEventHandler tempDelegate = new OnChangeEventHandler(dependency_OnChange); 

      object[] args = { sender, e }; 

      // Marshal the data from the worker thread 
      // to the UI thread. 
      i.BeginInvoke(tempDelegate, args); 

      return; 
     } 

     // Remove the handler, since it is only good 
     // for a single notification. 
     SqlDependency dependency = (SqlDependency)sender; 

     dependency.OnChange -= dependency_OnChange; 

     // At this point, the code is executing on the 
     // UI thread, so it is safe to update the UI. 
     ++changeCount; 
     lblChanges.Text = String.Format(statusMessage, changeCount); 

     // Reload the dataset that is bound to the grid. 
     GetData(); 
    } 

    AutoResetEvent running = new AutoResetEvent(true); 

    private void GetData() 
    { 
     // Start the retrieval of data on another thread to let the UI thread free 
     ThreadPool.QueueUserWorkItem(o => 
     { 
      running.WaitOne(); 

      // Empty the dataset so that there is only 
      // one batch of data displayed. 
      dataToWatch.Clear(); 

      // Make sure the command object does not already have 
      // a notification object associated with it. 
      command.Notification = null; 

      // Create and bind the SqlDependency object 
      // to the command object. 
      SqlDependency dependency = new SqlDependency(command); 

      dependency.OnChange += new OnChangeEventHandler(dependency_OnChange); 

      using (SqlDataAdapter adapter = new SqlDataAdapter(command)) 
      { 
       adapter.Fill(dataToWatch, tableName); 



       try 
       { 
        running.Set(); 
       } 
       finally 
       { 
        // Update the UI 
        dgv.Invoke(new Action(() => 
        { 
         dgv.DataSource = dataToWatch; 
         dgv.DataMember = tableName; 

         //dgv.FirstDisplayedScrollingRowIndex = dgv.Rows.Count - 1; 
        })); 
       } 


      } 
     }); 
    } 

    private void btnAction_Click(object sender, EventArgs e) 
    { 
     changeCount = 0; 
     lblChanges.Text = String.Format(statusMessage, changeCount); 

     // Remove any existing dependency connection, then create a new one. 
     SqlDependency.Stop("Server=.; Database=SMS_Tank_Log;UID=sa;PWD=hana;MultipleActiveResultSets=True"); 
     SqlDependency.Start("Server=.; Database=SMS_Tank_Log;UID=sa;PWD=hana;MultipleActiveResultSets=True"); 

     if (connection == null) 
     { 
      connection = new SqlConnection("Server=.; Database=SMS_Tank_Log;UID=sa;PWD=hana;MultipleActiveResultSets=True"); 

     } 

     if (command == null) 
     { 
      command = new SqlCommand("select * from OutgoingLog", connection); 

      //SqlParameter prm = 
      // new SqlParameter("@Quantity", SqlDbType.Int); 
      //prm.Direction = ParameterDirection.Input; 
      //prm.DbType = DbType.Int32; 
      //prm.Value = 100; 
      //command.Parameters.Add(prm); 
     } 

     if (dataToWatch == null) 
     { 
      dataToWatch = new DataSet(); 
     } 

     GetData(); 
    } 

    private void frmMain_Load(object sender, EventArgs e) 
    { 
     btnAction.Enabled = CanRequestNotifications(); 
    } 

    private void frmMain_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     SqlDependency.Stop("Server=.; Database=SMS_Tank_Log;UID=sa;PWD=hana;MultipleActiveResultSets=True"); 
    } 

問題: 我有錯誤,很多情況下,(第一評論圖片)

(第1號): 我得到這個錯誤對話框,和我不知道它的原因。我沒有在我的網格視圖(沒有錯誤,沒有數據)沒有得到任何東西。

(編號3): 雖然表中有行,但我只有列名和沒有行。

我需要幫助。

+0

**問題:** 我有很多錯誤的情況下, **(第1號)**: http://s7.postimg.org/9dpwvamej/image.png 我得到了這個錯誤,顯示在前面的鏈接。 **(No.2)**: http://s24.postimg.org/y1ln3hmsl/image.png 我在網格視圖中沒有任何內容。 **(No.3)**: http://s9.postimg.org/oh6qz8sn3/image.png 雖然表中有行,但我只有列名和沒有行。 我需要幫助。 –

回答

0

我可能是錯的,但一個數據集似乎並不具有通知能力,所以如果你改變它的背後的的DataGridView可能會感到驚訝。

你可以嘗試明確顯示your're首先將其設置爲空改變數據來源:

dgv.DataSource = null; 
dgv.DataSource = dataToWatch; 
dgv.DataMember = tableName; 

這是值得一試...

+0

不幸的是,它沒有奏效。我無法理解這三個錯誤的原因,以及錯誤的基本原理或它們出現的原因以及依賴於什麼? –

+0

並在「dgv.DataSource = null;」之後加上「dgv.Refresh()」? – Pragmateek

+0

dgv.DataSource = null; dgv.Refresh(); 此代碼腳本通過刪除數據源並再次重新綁定,使數據網格視圖閃爍不止一次。 我們需要一個新的場景來解決這個問題,首先將它運行到一個單獨的線程布爾中,避免出現這些錯誤。 因爲這個應用程序,我頭痛。 –