Search code examples
c#.netbackgroundworker

Getting errors while using Backgroundworkers


I am making dynamic dashboard and that's why all datagrids and datacharts should use background workers. Because sometimes getting data from the database takes 5-10 seconds and meanwhile application freezes if i don't use background workers. So using background workers are must for me.

If i don't use background workers i don't get any errors. However when i use background workers in different times (sometimes in 5 mins, sometimes after 1 hour) i get following errors;

1-) System.ArgumentException: An item with the same key has already been added
2-) object reference not set to an instance of an object

I don't know the reason for this. As i stated, If i don't use background workers, Everything works fine.

Here is the example code on the chart and usage of the backgroundworkers.

public void getTopSQL()

{
    dtTopSQL.Clear();
    odaTopSQL = new OracleDataAdapter(getTopSQLDetails, oradb);
    odaTopSQL.Fill(dtTopSQL);
    dtCurTopSQL.Merge(dtTopSQL); // Get current values from datatable dtTopSQL and add rows to general datatable 'dtCurTopSQL'

        if (dtCurTopSQL.AsEnumerable().Any() == true) // check for if datatable is not empty
        {
            maxDate = dtCurTopSQL.AsEnumerable().Max(z => z.Field<DateTime>("SAMPLE_TIME"));
            minDate = maxDate.AddSeconds(-90);
        }



        var isFull = dtCurTopSQL.AsEnumerable()  // check for if datatable is not empty
          .Where(l => l.Field<DateTime>("SAMPLE_TIME") >= minDate && l.Field<DateTime>("SAMPLE_TIME") <= maxDate).Any();



        if (isFull == true) // Here the magic happens.
        {
           var dt1 = dtCurTopSQL.AsEnumerable()
          .Where(l => l.Field<DateTime>("SAMPLE_TIME") >= minDate && l.Field<DateTime>("SAMPLE_TIME") <= maxDate)
          .GroupBy(h => h.Field<string>("SQL_ID"))
          .Select(g =>
          {
              DataRow row2 = dtCurTopSQL.NewRow();
              row2["SQL_ID"] = g.Key;
              row2["CountAll"] = g.Sum(h => h.Field<int>("CountAll"));
              row2["CPU"] = g.Sum(h => h.Field<int>("CPU"));
              row2["Scheduler"] = g.Sum(h => h.Field<int>("Scheduler"));
              row2["Activity"] = 0;
              return row2;
          }).CopyToDataTable();   
            ugTopSQL.DataSource = dt1;
        }

        else
        {
            ugTopSQL.DataSource = null;
        }                
}

private void bgwTA_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
 {
     getTA();
 }

try
{
    if (!bgwTA.IsBusy)
    {
        bgwTA.RunWorkerAsync();
    }
}
catch
{
    MessageBox.Show("Error : Wait Event Reader!");
}

Here is the stacktraces of the errors;

System.ArgumentException: An item with the same key has already been added.
   konum: System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   konum: System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   konum: Infragistics.Win.UltraWinGrid.UltraGridRow.get_ScrollCountInternal()
   konum: Infragistics.Win.UltraWinGrid.UltraGridRow.Infragistics.Shared.ISparseArrayMultiItem.get_ScrollCount()
   konum: Infragistics.Shared.SparseArray.EnsureScrollCountCalculatedHelper(NodeExtended n)
   konum: Infragistics.Shared.SparseArray.EnsureScrollCountCalculated()
   konum: Infragistics.Shared.SparseArray.GetVisibleCount()
   konum: Infragistics.Win.UltraWinGrid.RowsCollection.GetSpecialRowsHelper(List`1 list, Boolean top, UltraGridRow[] rowsToRecycle)
   konum: Infragistics.Win.UltraWinGrid.RowsCollection.CalcSpecialAndFixedRowsHelper(List`1& outSpecialRows, List`1& outFixedRows, Boolean top, UltraGridRow[] rowsToRecycle)
   konum: Infragistics.Win.UltraWinGrid.RowsCollection.EnsureSpecialAndFixedRowsCacheCalculated()
   konum: Infragistics.Win.UltraWinGrid.RowsCollection.GetFixedRows(Boolean top)
   konum: Infragistics.Win.UltraWinGrid.RowsCollection.HasFixedRows(Boolean top)
   konum: Infragistics.Win.UltraWinGrid.ViewStyleBase.get_Using_CreateRowsList_FixedRowsFeature()
   konum: Infragistics.Win.UltraWinGrid.ViewStyleBase.RecreateRowList(RowScrollRegion rsr, Boolean syncWithCalcManager)
   konum: Infragistics.Win.UltraWinGrid.RowScrollRegion.GetMaxScrollPosition(Boolean scrollToFill, Boolean ignoreScrollBoundsResolved)
   konum: Infragistics.Win.UltraWinGrid.RowScrollRegion.EnsureScrollRegionFilled(Boolean calledFromRegenerateVisibleRows)
   konum: Infragistics.Win.UltraWinGrid.RowScrollRegion.RegenerateVisibleRows(Boolean resetScrollInfo)
   konum: Infragistics.Win.UltraWinGrid.RowScrollRegion.RegenerateVisibleRows()
   konum: Infragistics.Win.UltraWinGrid.DataAreaUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UltraWinGrid.UltraGridUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UIElement.DrawHelper(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Boolean clipText, Boolean forceDrawAsFocused, Boolean preventAlphaBlendGraphics, Nullable`1 zoomFactor)
   konum: Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Size elementSize, Boolean preventAlphaBlendGraphics)
   konum: Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode)
   konum: Infragistics.Win.UltraWinGrid.UltraGridUIElement.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode)
   konum: Infragistics.Win.UltraControlBase.OnPaint(PaintEventArgs pe)
   konum: Infragistics.Win.UltraWinGrid.UltraGrid.OnPaint(PaintEventArgs pe)
   konum: System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
   konum: System.Windows.Forms.Control.WmPaint(Message& m)
   konum: System.Windows.Forms.Control.WndProc(Message& m)
   konum: System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   konum: System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   konum: System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

The Second one ;

System.NullReferenceException: object reference not set to an instance of an object.
   konum: Infragistics.Win.UltraWinGrid.UltraGridRow.get_BaseHeight()
   konum: Infragistics.Win.UltraWinGrid.VisibleRow.GetDimensions(ColScrollRegion csr, VisibleRowDimensions dimensions, DimOriginBase originBase)
   konum: Infragistics.Win.UltraWinGrid.RowColRegionIntersectionUIElement.PositionChildElements()
   konum: Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UltraWinGrid.RowColRegionIntersectionUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UltraWinGrid.DataAreaUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UltraWinGrid.UltraGridUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
   konum: Infragistics.Win.UIElement.DrawHelper(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Boolean clipText, Boolean forceDrawAsFocused, Boolean preventAlphaBlendGraphics, Nullable`1 zoomFactor)
   konum: Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Size elementSize, Boolean preventAlphaBlendGraphics)
   konum: Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode)
   konum: Infragistics.Win.UltraWinGrid.UltraGridUIElement.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode)
   konum: Infragistics.Win.UltraControlBase.OnPaint(PaintEventArgs pe)
   konum: Infragistics.Win.UltraWinGrid.UltraGrid.OnPaint(PaintEventArgs pe)
   konum: System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
   konum: System.Windows.Forms.Control.WmPaint(Message& m)
   konum: System.Windows.Forms.Control.WndProc(Message& m)
   konum: System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   konum: System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   konum: System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Solution

  • You have an issue where you seem to be trying to insert a key which already exists in the datatable, so this is not allowed. But I can't see your data so it is difficult to see the example problem.

    You do however have another issue, which might not cause you a problem yet but it will. That is that you can't make calls to UI elements (such as message Box) from a background worker.

    The UI elements are always on the main thread where as a background worker could be on any thread so you will first need to check and then call a delegate to invoke.

    But a better approach is to actually use the background worker events of

    ProgressChanged
    RunWorkerCompleted
    

    These are executed on the same thread which started the backgroundworker. So if you called this from your form then it will already be your UI thread. So this makes life easier.

    Your code is too long to repeat everything here, but I will give you an outline as to what is required.

    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += bgwTA_DoWork;
    worker.RunWorkerCompleted += bgwTA_RunWorkerCompleted;
    worker.RunWorkerAsync();
    
    private void bgwTA_DoWork(object sender, DoWorkEventArgs e)
    {
        dtTopSQL.Clear();
        odaTopSQL = new OracleDataAdapter(getTopSQLDetails, oradb);
        odaTopSQL.Fill(dtTopSQL);
        //etc
    
        e.Result = dt1;
    }
    
    private void bgwTA_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
       {
        if (e.Cancelled)
        {
            //Process was cancelled, need to clean up here
        }
        else if (e.Error != null)
        {
            //Here was an error running the process. or the thread aborted.  
            //Need to raise errors and clean up here
            //If your process threw an exception, then it will be here                
        }
        else
        {
            //Everything worked OK, now we can update our UI elements
            //The Worker Completed thread will come back to the thread which called it.  Which, means if called from you main UI thread that you don't have to use invoke
    
            ugTopSQL.DataSource = (DataTable)e.Result;
        }
    }