Deadlock Problem

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,
I have a MDI WinForm Client App. I keep a static Master DataSet and a static
Master Hashtable. When I connect to the Server, it sends me a Master DataSet
and I copy it to the static Master DataSetand also create a static Master
Hashtable with DataRow as value and Symbol as a key. I need Master Hashtable
for fast retrival.

That was the initial connect. Updates from server also comes as a Hashtable
with name-value pairs via TIBCO Message Bus. I retrive the Symbol using
"SYMBOL" as key from the update Hashtable, get the DataRow from static Master
Hashtable using that symbol and update the DataRow with name-value update
Hashtable.

Inside MDI Form I can create n number of forms, each from would have a
different view on the static Master DataSet using .NET DataView.

Everything runs fine. All the views get updates, since all are bound to a
DataView on a Static Master DataSet. Then suddenly after 2-3 hours, the
client doesn't respond and the size of the TIBCO message bus grows.

It hung up on DataRow.AcceptChanges() method.

My question is, is it alright to update the DataSet on a thread different
than a thread that created the Grid to which the DataSet is bound? I know
that when you update a control you have to call Invoke or Begin Invoke on
that control and etc. etc. .....

If its not the right way of doing then I can't afford to update the DataSet
on the main thread that created the forms and controls (including grid)
because the number of updates are too high (10000 per minutes with ~90
columns in a row) and that would affect user interaction with the application.

Is there any workaround?

Any help/idea is appreciated.

Thanks a lot,
Lalit
 
This is not a deadlock problem. It's likely a performance issue or an
unhandled exception.
The dataaset has thread affinity to the main thread and its also tied to the
dataview object so you need to correctly marshal your update calls using
invoke. I don't understand why you have a dataset and a hashtable though.
You can do without the one. I'm not sure how much performance improvement
you are getting from a hashtable as opposed to a dataset find routine. The
dataset find routine uses an optimized indexer underneath so retrievals are
fast.

Another problem i see is that you have a master dataset but it doesn't
appear to be wrapped in a class. So you can possibly cause the dataset grief
if multiple forms trigger the acceptchanges function within a short space of
time or at the same time. Datasets weren't meant for concurrent access.
--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://tinyurl.com/27cok
 
Alvin,
Thanks for the reply.

I didn't know that DataSet too has thread affinity to the thread on which it
was created (not the main thread, typo I guess). In any case, I am updating
the DataSet on the same thread that created it.

Find routine is too slow for large number of hits.

DataSet is updated by a single thread all the time, in a sequential manner.
Its not the Form that updates the DataSet, its the message that TIBCO sends
as a Hashtable. Since the Grid is bound to that DataSet and each instance of
that form has a DataView on this Master DataSet, the view is updated as soon
as the Row is updated.

Probablity of it being a performance issues or unhandles exception is less
because I am logging all the exception that I handle and I am handling all
the exceptions.

My question still remain the same:
- is it alright to update the DataSet on a thread different than a thread
(its still the same thread that created the DataSet) that created the Grid to
which the DataSet is bound?

- If its not the right way of doing then I can't afford to update the
DataSet on the main thread that created the forms and controls (including
grid) because the number of updates are too high (10000 per minutes with ~90
columns in a row) and that would affect user interaction with the application.
Is there any workaround?

Thanks a lot.
Lalit
 
This is not a deadlock problem. It's likely a performance issue or an
unhandled exception.
The dataaset has thread affinity to the main thread and its also tied to the
dataview object so you need to correctly marshal your update calls using
invoke.

Just to clarify - I don't think DataSets naturally have thread affinity
- it's when modifying them makes a UI do something that you have
problems. If you can unbind all the controls from the DataSet, make the
modifications, then put the bindings in again, I think that's fine.
(Alternatively, have a "working" DataSet and a "display" DataSet, and
when all the work has been done, make all the changes again in the
display version.)

That's the way I understand it, but I may be wrong, in which case I
definitely want to know!
 
DataSet is too big, 5000 rows with ~90 columns, and update are coming at
~10000 per minute. Unbinding and binding again would definitelty affect the
performance and there could be n number of instance of a form that would
display different views on the same dataset.

Lalit
 
My question still remain the same:
- is it alright to update the DataSet on a thread different than a thread
(its still the same thread that created the DataSet) that created the Grid
to
which the DataSet is bound? Yes.

Find routine is too slow for large number of hits.
Which find routine, the dataset's find routine or a find routine that you
implemented separately? Did you test this?
DataSet is updated by a single thread all the time, in a sequential
manner.
How can this possibly be? You have 10,000+ updates being triggered by TIBCO
thru a hashtable on a per form basis, each form being tied to a view which
is sourced from a global dataset. Unless TIBCO is throttling the updates
sequentially, you stand a chance of concurrent access. I suspect, you have
no type of protection on that global dataset but you are using the dataset
as if it was synchronized for access. That is my leading theory at this
time.

It is time to see some relevant code.

--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://www.lulu.com/owc
----------------------------------------------------------


Lalit said:
Alvin,
Thanks for the reply.

I didn't know that DataSet too has thread affinity to the thread on which
it
was created (not the main thread, typo I guess). In any case, I am
updating
the DataSet on the same thread that created it.

Find routine is too slow for large number of hits.

DataSet is updated by a single thread all the time, in a sequential
manner.
Its not the Form that updates the DataSet, its the message that TIBCO
sends
as a Hashtable. Since the Grid is bound to that DataSet and each instance
of
that form has a DataView on this Master DataSet, the view is updated as
soon
as the Row is updated.

Probablity of it being a performance issues or unhandles exception is less
because I am logging all the exception that I handle and I am handling all
the exceptions.

My question still remain the same:
- is it alright to update the DataSet on a thread different than a thread
(its still the same thread that created the DataSet) that created the Grid
to
which the DataSet is bound?

- If its not the right way of doing then I can't afford to update the
DataSet on the main thread that created the forms and controls (including
grid) because the number of updates are too high (10000 per minutes with
~90
columns in a row) and that would affect user interaction with the
application.
Is there any workaround?

Thanks a lot.
Lalit

Alvin Bruney said:
This is not a deadlock problem. It's likely a performance issue or an
unhandled exception.
The dataaset has thread affinity to the main thread and its also tied to
the
dataview object so you need to correctly marshal your update calls using
invoke. I don't understand why you have a dataset and a hashtable though.
You can do without the one. I'm not sure how much performance improvement
you are getting from a hashtable as opposed to a dataset find routine.
The
dataset find routine uses an optimized indexer underneath so retrievals
are
fast.

Another problem i see is that you have a master dataset but it doesn't
appear to be wrapped in a class. So you can possibly cause the dataset
grief
if multiple forms trigger the acceptchanges function within a short space
of
time or at the same time. Datasets weren't meant for concurrent access.
--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://tinyurl.com/27cok
----------------------------------------------------------
 
Just to clarify - I don't think DataSets naturally have thread affinity
Yes this is technically correct. But since a dataset is usually tightly
coupled to a view (UI piece) or may contain embedded UI objects then the
issues arise. I should have been more accurate with my post.

--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://www.lulu.com/owc
 
As per my investigations Find method of DataSet is slower than using Hashtable.

If you could tell me you e-mail ID I would like you to take a look at the
code. I do not see a way to attach a file on this newsgroup.

Yeah TIBCO is throttling the updates sequentially. If I need to make the
process faster I need to create a thread as soon as I get the update and then
update the DataSet, but I am not doing it at this point in time.

Thanks,
Lalit

Alvin Bruney said:
My question still remain the same:
- is it alright to update the DataSet on a thread different than a thread
(its still the same thread that created the DataSet) that created the Grid
to
which the DataSet is bound? Yes.

Find routine is too slow for large number of hits.
Which find routine, the dataset's find routine or a find routine that you
implemented separately? Did you test this?
DataSet is updated by a single thread all the time, in a sequential
manner.
How can this possibly be? You have 10,000+ updates being triggered by TIBCO
thru a hashtable on a per form basis, each form being tied to a view which
is sourced from a global dataset. Unless TIBCO is throttling the updates
sequentially, you stand a chance of concurrent access. I suspect, you have
no type of protection on that global dataset but you are using the dataset
as if it was synchronized for access. That is my leading theory at this
time.

It is time to see some relevant code.

--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://www.lulu.com/owc
----------------------------------------------------------


Lalit said:
Alvin,
Thanks for the reply.

I didn't know that DataSet too has thread affinity to the thread on which
it
was created (not the main thread, typo I guess). In any case, I am
updating
the DataSet on the same thread that created it.

Find routine is too slow for large number of hits.

DataSet is updated by a single thread all the time, in a sequential
manner.
Its not the Form that updates the DataSet, its the message that TIBCO
sends
as a Hashtable. Since the Grid is bound to that DataSet and each instance
of
that form has a DataView on this Master DataSet, the view is updated as
soon
as the Row is updated.

Probablity of it being a performance issues or unhandles exception is less
because I am logging all the exception that I handle and I am handling all
the exceptions.

My question still remain the same:
- is it alright to update the DataSet on a thread different than a thread
(its still the same thread that created the DataSet) that created the Grid
to
which the DataSet is bound?

- If its not the right way of doing then I can't afford to update the
DataSet on the main thread that created the forms and controls (including
grid) because the number of updates are too high (10000 per minutes with
~90
columns in a row) and that would affect user interaction with the
application.
Is there any workaround?

Thanks a lot.
Lalit

Alvin Bruney said:
This is not a deadlock problem. It's likely a performance issue or an
unhandled exception.
The dataaset has thread affinity to the main thread and its also tied to
the
dataview object so you need to correctly marshal your update calls using
invoke. I don't understand why you have a dataset and a hashtable though.
You can do without the one. I'm not sure how much performance improvement
you are getting from a hashtable as opposed to a dataset find routine.
The
dataset find routine uses an optimized indexer underneath so retrievals
are
fast.

Another problem i see is that you have a master dataset but it doesn't
appear to be wrapped in a class. So you can possibly cause the dataset
grief
if multiple forms trigger the acceptchanges function within a short space
of
time or at the same time. Datasets weren't meant for concurrent access.
--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://tinyurl.com/27cok
----------------------------------------------------------
 
See this link, http://www.yoda.arachsys.com/csharp/complete.html
then post

--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://www.lulu.com/owc
----------------------------------------------------------


Lalit said:
As per my investigations Find method of DataSet is slower than using
Hashtable.

If you could tell me you e-mail ID I would like you to take a look at the
code. I do not see a way to attach a file on this newsgroup.

Yeah TIBCO is throttling the updates sequentially. If I need to make the
process faster I need to create a thread as soon as I get the update and
then
update the DataSet, but I am not doing it at this point in time.

Thanks,
Lalit

Alvin Bruney said:
My question still remain the same:
- is it alright to update the DataSet on a thread different than a
thread
(its still the same thread that created the DataSet) that created the
Grid
to
which the DataSet is bound? Yes.

Find routine is too slow for large number of hits.
Which find routine, the dataset's find routine or a find routine that you
implemented separately? Did you test this?
DataSet is updated by a single thread all the time, in a sequential
manner.
How can this possibly be? You have 10,000+ updates being triggered by
TIBCO
thru a hashtable on a per form basis, each form being tied to a view
which
is sourced from a global dataset. Unless TIBCO is throttling the updates
sequentially, you stand a chance of concurrent access. I suspect, you
have
no type of protection on that global dataset but you are using the
dataset
as if it was synchronized for access. That is my leading theory at this
time.

It is time to see some relevant code.

--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://www.lulu.com/owc
----------------------------------------------------------


Lalit said:
Alvin,
Thanks for the reply.

I didn't know that DataSet too has thread affinity to the thread on
which
it
was created (not the main thread, typo I guess). In any case, I am
updating
the DataSet on the same thread that created it.

Find routine is too slow for large number of hits.

DataSet is updated by a single thread all the time, in a sequential
manner.
Its not the Form that updates the DataSet, its the message that TIBCO
sends
as a Hashtable. Since the Grid is bound to that DataSet and each
instance
of
that form has a DataView on this Master DataSet, the view is updated as
soon
as the Row is updated.

Probablity of it being a performance issues or unhandles exception is
less
because I am logging all the exception that I handle and I am handling
all
the exceptions.

My question still remain the same:
- is it alright to update the DataSet on a thread different than a
thread
(its still the same thread that created the DataSet) that created the
Grid
to
which the DataSet is bound?

- If its not the right way of doing then I can't afford to update the
DataSet on the main thread that created the forms and controls
(including
grid) because the number of updates are too high (10000 per minutes
with
~90
columns in a row) and that would affect user interaction with the
application.
Is there any workaround?

Thanks a lot.
Lalit

:

This is not a deadlock problem. It's likely a performance issue or an
unhandled exception.
The dataaset has thread affinity to the main thread and its also tied
to
the
dataview object so you need to correctly marshal your update calls
using
invoke. I don't understand why you have a dataset and a hashtable
though.
You can do without the one. I'm not sure how much performance
improvement
you are getting from a hashtable as opposed to a dataset find routine.
The
dataset find routine uses an optimized indexer underneath so
retrievals
are
fast.

Another problem i see is that you have a master dataset but it doesn't
appear to be wrapped in a class. So you can possibly cause the dataset
grief
if multiple forms trigger the acceptchanges function within a short
space
of
time or at the same time. Datasets weren't meant for concurrent
access.
--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://tinyurl.com/27cok
 
I am pasting the code that shows that Hash is faster than Find Method of
RowCollection.

At this point in time I can't post the code that is within your specs and
that reproduce the deadlock because of time constraint. I can give you some
of the classes as it is just to look at, if you want.

Thanks a lot,
Lalit


using System;
using System.Data;
using System.Collections;

public class MyClass
{
public static void Main()
{
RL();
}

private static void RL()
{
try
{
Hashtable hash = new Hashtable();
DataSet ds = new DataSet();
DataTable table = new DataTable();
table.Columns.Add("Id", Type.GetType("System.Int32"));
table.Columns.Add("Name", Type.GetType("System.String"));
table.PrimaryKey = new DataColumn[] {table.Columns["Id"]};
ds.Tables.Add(table);

for(int i = 0; i < 1000000; i++)
{
DataRow dr = table.NewRow();
dr["Id"] = i;
dr["Name"] = i.ToString();
hash.Add(i, dr);
table.Rows.Add(dr);
}

Console.WriteLine(ds.Tables[0].Rows.Count.ToString());

DateTime t1 = DateTime.Now;
for(int i = 0; i < 1000000; i++)
{
int j = new Random(unchecked((int)DateTime.Now.Ticks)).Next(1000000 - 1);
DataRow dr = table.NewRow();
dr["Id"] = j;
dr["Name"] = j.ToString();

DataRow r = ds.Tables[0].Rows.Find(j);
}
DateTime t2 = DateTime.Now;
Console.WriteLine(t2-t1);

t1 = DateTime.Now;
for(int i = 0; i < 1000000; i++)
{
int j = new Random(unchecked((int)DateTime.Now.Ticks)).Next(1000000 - 1);
DataRow dr = table.NewRow();
dr["Id"] = j;
dr["Name"] = j.ToString();

DataRow r = (DataRow) hash[j];
}
t2 = DateTime.Now;
Console.WriteLine(t2-t1);

Console.ReadLine();
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
}

}

public class Person
{
private int id;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}

private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
 
Back
Top