2013-06-11 4 views
0

У меня есть приложение Windows, использующее SqlDependency, запущенное в отдельном пуле потоков, это приложение представляет собой пользовательский интерфейс мониторинга журналов, который получает последние строки, добавленные в конкретную таблицу в базе данных, и просматривает их в 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"); 
    } 

Проблема: У меня есть много ситуаций, ошибок, (изображения в первом комментарии)

(No. 1): Я получил этот диалог ошибки, и я не знаю его причины.

(№ 2): У меня ничего не было в виде сетки (нет ошибок и нет данных).

(No. 3): У меня есть только имена столбцов и нет строк, хотя в таблице есть строки.

Мне нужна помощь, пожалуйста.

+0

** Проблема: ** I имеют много ошибок, ** (№ 1) **: http://s7.postimg.org/9dpwvamej/image.png Я получил эту ошибку, показанную в предыдущей ссылке. ** (№ 2) **: http://s24.postimg.org/y1ln3hmsl/image.png У меня ничего не было в виде сетки. ** (№ 3) **: http://s9.postimg.org/oh6qz8sn3/image.png У меня есть только имена столбцов и строк, хотя в таблице есть строки. Мне нужна помощь, пожалуйста. –

ответ

0

Я могу ошибаться, но DataSet, кажется, не имеет уведомления о возможности так DataGridView может быть удивлен, если вы измените его за спиной.

Вы можете попробовать явно показать вы как раз при изменении источника данных, первым установив его на нуль:

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

Это стоит попробовать ...

+0

К сожалению, это не сработало. Я не могу понять причину этих трех ошибок, а также каковы основы ошибок или почему они появляются и от чего зависит? –

+0

И с "dgv.Refresh()" после "dgv.DataSource = null;"? – Pragmateek

+0

dgv.DataSource = null; dgv.Refresh(); этот скрипт кода делает вид сетки данных мигает более одного раза с одной секундой, удаляя источник данных и снова переписывая. Нам нужен новый сценарий для этой проблемы, начиная запускать его в отдельный поток bool, избегая этих ошибок. У меня болит голова из-за этого приложения. –