Exception

G

Guest

I m creating a multithreaded application in which a the datasource of a
datagridview is being updated from an other thread..

the following piece of code is here

private void UpdateGridView(DataSet ds)
{
try
{
DataSet nds = FlipDataSet(ds);
dataGridView1.DataSource = nds.Tables[0].DefaultView; //Exception
thrown when executing this statement. nds.Tables[0].DefaultView is not null
dataGridView1.Refresh();
}
catch
{

}
}

when the above portion of code executes, though it is inside the try catch
block, I get a NullReferenceException and here is the stack trace details

at System.Windows.Forms.DataGridViewRowHeaderCell.PaintPrivate(Graphics
graphics,

Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex,
DataGridViewElementStates

dataGridViewElementState, Object formattedValue, String errorText,

DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle
advancedBorderStyle,

DataGridViewPaintParts paintParts, Boolean computeContentBounds, Boolean

computeErrorIconBounds, Boolean paint)
at System.Windows.Forms.DataGridViewRowHeaderCell.Paint(Graphics
graphics,

Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex,
DataGridViewElementStates

cellState, Object value, Object formattedValue, String errorText,

DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle
advancedBorderStyle,

DataGridViewPaintParts paintParts)
at System.Windows.Forms.DataGridViewCell.PaintWork(Graphics graphics,
Rectangle

clipBounds, Rectangle cellBounds, Int32 rowIndex, DataGridViewElementStates

cellState, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle

advancedBorderStyle, DataGridViewPaintParts paintParts)
at System.Windows.Forms.DataGridViewRow.PaintHeader(Graphics graphics,
Rectangle

clipBounds, Rectangle rowBounds, Int32 rowIndex, DataGridViewElementStates
rowState,

Boolean isFirstDisplayedRow, Boolean isLastVisibleRow,
DataGridViewPaintParts

paintParts)
at System.Windows.Forms.DataGridViewRow.Paint(Graphics graphics,
Rectangle

clipBounds, Rectangle rowBounds, Int32 rowIndex, DataGridViewElementStates
rowState,

Boolean isFirstDisplayedRow, Boolean isLastVisibleRow)
at System.Windows.Forms.DataGridView.PaintRows(Graphics g, Rectangle
boundingRect,

Rectangle clipRect, Boolean singleHorizontalBorderAdded)
at System.Windows.Forms.DataGridView.PaintGrid(Graphics g, Rectangle
gridBounds,

Rectangle clipRect, Boolean singleVerticalBorderAdded, Boolean

singleHorizontalBorderAdded)
at System.Windows.Forms.DataGridView.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e,
Int16

layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.DataGridView.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg,

IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at

System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMe

thods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32
reason, Int32

pvLoopData)
at
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32

reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32
reason,

ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Scanner.Program.Main() in G:\UserDocs\Rajkiran's Documents

\Visual Studio 2008\Projects\Scanner

\Scanner\Program.cs:line 17
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence

assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext,

ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Please help me in resolving this.
 
G

Gregory A. Beamer

I m creating a multithreaded application in which a the datasource of a
datagridview is being updated from an other thread..

I did not examine the code, but it sounds like you are having a threading
issue. To talk to the main thread, which has control of your form, consider
using an event with an event handler (ie, delegate the work back to the
main thread). This way the application can spawn the longer running process
(assume it is longer running and the reason for asynchronous data updates)
and handle it when it is finished.

There is probably another way to solve the issue, but this is my first
crack at it.

Peace and Grace,
Greg

--
Vote for Miranda's Christmas Story
http://tinyurl.com/mirandabelieve

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

*******************************************
| Think outside the box! |
*******************************************
 
P

Peter Duniho

Gregory said:
I m creating a multithreaded application in which a the datasource of a
datagridview is being updated from an other thread..

I did not examine the code, but it sounds like you are having a threading
issue. To talk to the main thread, which has control of your form, consider
using an event with an event handler (ie, delegate the work back to the
main thread). [...]

An event with an event handler doesn't do anything at all to do with
cross-thread/inter-thread issues. The only way to "delegate the work
back to the main thread" is to use some specific cross-thread invocation
mechanism that is designed for that (e.g. Control.Invoke()).

Pete
 
P

Peter Duniho

I m creating a multithreaded application in which a the datasource of a
datagridview is being updated from an other thread..

the following piece of code is here

private void UpdateGridView(DataSet ds)
{
try
{
DataSet nds = FlipDataSet(ds);
dataGridView1.DataSource = nds.Tables[0].DefaultView;
//Exception thrown when executing this statement.
nds.Tables[0].DefaultView is not null
dataGridView1.Refresh();
}
catch
{

}
}

That's not nearly enough code for anyone to do anything useful with it.

It's possible that you should be using Control.Invoke() to ensure that
the DataSource update happens on the thread that owns the DataGridView
control instance. But even that, there's not enough code in your post
for anyone to know you're not _already_ doing that.

The stack trace clearly shows that there's something wrong with the
DataGridView row header drawing, maybe other parts too (but of course
you only get to see the very first exception :) ). And you definitely
should not be calling Refresh() on any thread other than the one that
owns the DataGridView control (though frankly, you really should not be
calling Refresh() at all IMHO). But again, so far there's no evidence
you are doing that in the first place.

If you want more specific help, you need to post a concise-but-complete
code example that reliably demonstrates the problem.

Pete
 
G

Guest

Well I got it working by hiding the datagridview before assigning the data
source and then showing it up again after assigning the datasource.
private void UpdateGridView(DataSet ds)
{
try
{
DataSet nds = FlipDataSet(ds);
dataGridView1.Visible = false;
dataGridView1.DataSource = nds.Tables[0].DefaultView;
dataGridView1.Visible = true;
dataGridView1.Refresh();
}
catch
{

}


Thought the issues is resolved, is this a right way...
--
Thanks & Regards
Rajkiran Ramachandran Balasubramanian

Peter Duniho said:
I m creating a multithreaded application in which a the datasource of a
datagridview is being updated from an other thread..

the following piece of code is here

private void UpdateGridView(DataSet ds)
{
try
{
DataSet nds = FlipDataSet(ds);
dataGridView1.DataSource = nds.Tables[0].DefaultView;
//Exception thrown when executing this statement.
nds.Tables[0].DefaultView is not null
dataGridView1.Refresh();
}
catch
{

}
}

That's not nearly enough code for anyone to do anything useful with it.

It's possible that you should be using Control.Invoke() to ensure that the
DataSource update happens on the thread that owns the DataGridView control
instance. But even that, there's not enough code in your post for anyone
to know you're not _already_ doing that.

The stack trace clearly shows that there's something wrong with the
DataGridView row header drawing, maybe other parts too (but of course you
only get to see the very first exception :) ). And you definitely should
not be calling Refresh() on any thread other than the one that owns the
DataGridView control (though frankly, you really should not be calling
Refresh() at all IMHO). But again, so far there's no evidence you are
doing that in the first place.

If you want more specific help, you need to post a concise-but-complete
code example that reliably demonstrates the problem.

Pete
 
P

Peter Duniho

Well I got it working by hiding the datagridview before assigning the
data source and then showing it up again after assigning the datasource.
[...]
Thought the issues is resolved, is this a right way...

Almost certainly not. Hiding a control and then showing it again later
as a means of addressing a possible multi-threading issue has "awful
hack" written all over it.

But until you post a concise-but-complete code example that reliably
reproduces your problem, nobody will be able to say anything definitive
at all about that problem or what the right way to fix it is.

Pete
 
G

Guest

Well its just a simple form with a datagridview and a button and a text
box..
Whenever the button is clicked it start a new thread which populates the
required data and sets it to the datagridview.
When I try to set the datasource propery of the datagridview in the same
thread, no exception is thrown, though the application is non responsive for
few seconds and then resumes after the data is populated. However when I do
it using a separate thread then I get error if I don hide the datagridview
before setting the datasource property.
--
Thanks & Regards
Rajkiran Ramachandran Balasubramanian

Peter Duniho said:
Well I got it working by hiding the datagridview before assigning the
data source and then showing it up again after assigning the datasource.
[...]
Thought the issues is resolved, is this a right way...

Almost certainly not. Hiding a control and then showing it again later as
a means of addressing a possible multi-threading issue has "awful hack"
written all over it.

But until you post a concise-but-complete code example that reliably
reproduces your problem, nobody will be able to say anything definitive at
all about that problem or what the right way to fix it is.

Pete
 
G

Guest

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DBHelpers.MyDataSetTableAdapters;
using DBHelpers;

namespace Scanner
{
public partial class ProcessThread : Form
{

public ScannerMain()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;
}

private void AppendThread()
{
try
{

ProcessTableAdapter adpProcess = new
ProcessTableAdapter();
MyDataSet.ProcessDataTable datatable =
adpsProcess.GetDataByProcessName(textBox1.Text);
DataSet ds = new DataSet();
ds.Tables.Add(datatable);
DataSet nds = FlipDataSet(ds);
dt = nds.Tables[0];
dataGridView1.DataSource = dt.DefaultView;

}
catch
{

}


}



private DataSet FlipDataSet(DataSet my_DataSet)
{
DataSet ds = new DataSet();

foreach (DataTable dt in my_DataSet.Tables)
{
DataTable table = new DataTable();

for (int i = 0; i <= dt.Rows.Count; i++)
{ table.Columns.Add(Convert.ToString(i)); }

DataRow r;
for (int k = 0; k < dt.Columns.Count; k++)
{
r = table.NewRow();
r[0] = dt.Columns[k].ToString();
for (int j = 1; j <= dt.Rows.Count; j++)
{ r[j] = dt.Rows[j - 1][k]; }
table.Rows.Add(r);
}
ds.Tables.Add(table);
}

return ds;
}



private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return)
{
if (textBox1.Text != string.Empty)
{
System.Threading.Thread th = new
System.Threading.Thread(new System.Threading.ThreadStart(ProcessThread));
th.Start();
}
}
}
}
}


--
Thanks & Regards
Rajkiran Ramachandran Balasubramanian

Peter Duniho said:
Well I got it working by hiding the datagridview before assigning the
data source and then showing it up again after assigning the datasource.
[...]
Thought the issues is resolved, is this a right way...

Almost certainly not. Hiding a control and then showing it again later as
a means of addressing a possible multi-threading issue has "awful hack"
written all over it.

But until you post a concise-but-complete code example that reliably
reproduces your problem, nobody will be able to say anything definitive at
all about that problem or what the right way to fix it is.

Pete
 
P

Peter Duniho

Well its just a simple form with a datagridview and a button and a text
box..
Whenever the button is clicked it start a new thread which populates the
required data and sets it to the datagridview.
When I try to set the datasource propery of the datagridview in the same
thread, no exception is thrown, though the application is non responsive
for few seconds and then resumes after the data is populated. However
when I do it using a separate thread then I get error if I don hide the
datagridview before setting the datasource property.

Again, without a concise-but-complete code example that reliably
reproduces the problem, nothing definitive can be stated.

That said, your description sounds exactly like the kind of problem that
is correctly fixed by using the Control.Invoke() method to execute any
code that actually interacts with a Control instance on the thread that
owns that Control instance.

This doesn't necessarily mean the data acquisition should happen on that
thread. But certainly anything that could update the presentation of
that data to the user should be.

Pete
 
P

Peter Duniho

The code you posted is not a concise-but-complete code example that
reliably demonstrates the problem. However, this is a clear problem:

[...]
public ScannerMain()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;
}

You are specifically disabling the one thing that would allow the
debugger to alert you to a bug in your code. NEVER set
"CheckForIllegalCrossThreadCalls" to "false".

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top