|
Although the execution of multiple events cannot be performed simultaneously on a single CPU, they can certainly be interlaced since they are executing on separate threads. The usage of synchronization techniques still applies. Furthermore, making assumptions about the hardware and how it relates to thread synchronization is a dangerous road to go down.
Brian
|
|
|
|
|
Thanks for these comments.
From the comments made earlier I was starting to think that my understanding of the need for synchronization was completely wrong. Your comments have really cleared things up for me.
|
|
|
|
|
I would intentionally leave the ThreadTest class unsafe for multithreading. Inform the subscribers of this class' event that it is executed on another thread. Let the subscribers handle their own synchronization. Remember, the ThreadTest class is not safe for multithreading so that means subscribing and unsubscribing to the event is also not safe multithreading. Here's how the code might look...
public class ThreadTest
{
public event EventHandler MyEvent;
public void Start()
{
Thread thread = new Thread(new ThreadStart(this.ThreadMethod));
thread.Start();
}
private void ThreadMethod()
{
while (true)
{
Thread.Sleep(1000);
if (MyEvent != null) MyEvent(this, EventArgs.Empty);
}
}
}
public class Subscriber
{
public void Run()
{
ThreadTest test = new ThreadTest();
test.MyEvent += new EventHandler(this.OnEvent);
test.Start();
test.Start();
test.Start();
}
public void OnEvent(object source, EventArgs e)
{
lock (this)
{
}
}
}
|
|
|
|
|
Thanks for the suggestions Brian. This is just the sort of help I was after.
|
|
|
|
|
Hummmm, but because of one reason, you may need to use lock in your first example.
Consider below situation:
A thread(say thread_A ) reaches here:
if (<code>Event </code>!= null){
<code>Event</code>(<code>this</code>, <code>e</code>);
}
thread_A checks and sees that Event is not null , and goes to fire Event (this, e). But before calling it, its time slice terminates. Now suppose that in our main application, by using -= operator the Event gets null. Now it's thread_A 's turn to continue. But an exception will be fired by calling Event (this, e). This will not happen be using below code:
lock(this){
if (<code>Event </code>!= null){
<code>Event</code>(this, e);
}
}
I am wondered why below code doesn't lock the Event and the exception would occur:
lock(<code>Event</code>){
if (<code>Event </code>!= null){
<code>Event</code>(this, e);
}
}
Don't forget, that's Persian Gulf not Arabian gulf!
|
|
|
|
|
Your example is interesting but I think that your suggested solution is flawed. Placing the lock around the event raising code e.g.
lock(this) {
if (Event != null) {
Event(this, e);
}
}
will not stop our main application from using -= operator on the Event. The lock places the event raising code in a critical section. It does not stop other threads accessing the Event property.
What do you think?
|
|
|
|
|
I don't think;), I tried it and it worked seamlessly!
Don't forget, that's Persian Gulf not Arabian gulf!
|
|
|
|
|
OK ... How about posting your test code.
|
|
|
|
|
I just need your e-mail to send source code for you.
Don't forget, that's Persian Gulf not Arabian gulf!
|
|
|
|
|
You were lucky
|
|
|
|
|
Brian Gideon wrote:
You were lucky
I can post the source code for you and you will see you are more lucky than me after running it and having no exception! ;P (need for your mail)
Don't forget, that's Persian Gulf not Arabian gulf!
|
|
|
|
|
TimK wrote:
What do you think?
You are correct.
|
|
|
|
|
I mentioned this problem briefly in my original post. My example code assumes that all event handlers have been added prior to calling ThreadTest.Start(). It's easy is see that unsubscribing with -= will cause a lot of problems after the threads have been started, but += could be problematic as well. This problem is difficult solve correctly and that is why I suggested to intentionally leave the ThreadTest class unsafe for multithreading.
Simply locking the code that raises the event is insufficient. You must lock the -= and += operators as well. This can be done with special syntax, using the add and remove keywords.
public class ThreadTest
{
private ArrayList _events = new ArrayList();
public event EventHandler MyEvent
{
add { lock (this) { _events.Add(value); } }
remove { lock (this) { _events.Remove(value); } }
}
public void Start()
{
}
private void ThreadMethod()
{
while (true)
{
ArrayList clone;
lock (this)
{
clone = (ArrayList)_events.Clone();
}
foreach (EventHandler e in clone)
{
e.DynamicInvoke(...);
}
}
}
}
If you're going to do this you might as well make every method on ThreadTest thread-safe to avoid confusion and inconsistency. This solution still requires that subscribers handle their on synchronization.
Brian
|
|
|
|
|
I have a DataGrid bound to source. The source table has a column that contains status numbers (integers), and the dataGrid shows these numbers. I have another table in the database which associates these numbers with a string.
Does anyone know of a way I can make the dataGrid show the associated string (from the other table) instead of the numbers in the current table?
-- James --
|
|
|
|
|
Add next table to the DataSet with Your dictionary and create relation into it. See Expression property of DataColumn. It can do this association.
Hi,
AW
|
|
|
|
|
Why don't you make a "Select" Query with a join and create a DataTable in memory to display it on the grid ?
HTH
Braulio
|
|
|
|
|
Thanks AW and Braulio for the ideas. I'll explore these.
-- James --
|
|
|
|
|
I'm looking to sort a ListView in detailed view with ascending/descending. Something like Explorer where the arrows are shown, as well.
I've got a class that someone else in there now, but it only sorts ascending and it's not "intelligent" with numbers; it sorts 1 10 11 12 ... 2 20 etc.
Apparently this isn't built in to the ListView object itself, so does anyone have a nice custom class that does this?
|
|
|
|
|
There's a ListViewSorter implementation in the Genghis Project[^] that includes chevrons, though I have found the chevron implementation to be quite buggy.
You might also like to check out the ListViewFilter[^] article here on CP.
|
|
|
|
|
though I have found the chevron implementation to be quite buggy.
Wow, you weren't kidding. I got an exception after every other sort. It did exactly what I wanted though; hope they look into making it a bit more stable.
|
|
|
|
|
I was wondering if there is any (preferably relatively straighforward) way for a method in C# to obtain the object which made the call. For example...
namespace Example
{
public class A
{
private B b;
public A()
{
b = new B();
b.Call();
}
}
public class B
{
public B()
{
}
public void Call()
{
object caller = null;
}
}
}
I hope this makes some sense. Any hints / tips are much appreciated.
--
The Last Bastion
|
|
|
|
|
|
Have a look at the stack trace objects in the debugging namespace, cant remember offhand where it is (not on a .NET Pc at the moment!) System.Diagnostics might be the one. Not 100% sure if it returns the object, or just a list of methods called.
Cheers, James
James Simpson
Web Developer
imebgo@hotmail.com
|
|
|
|
|
|
leppie wrote:
hey where is the object?
There isn't one, also what would you do if the caller was a static method? In that case there is no object reference that is doing the calling.
AFAIK, the best you can hope for is to get the class/struct name and possibly get the Type object representing it.
James
At Jethro Tull's August 28, 2003 concert Ian Anderson mentioned that the group would be performing a medley of title tracks. The songs were "Songs from the Wood", "Too Old to Rock and Roll; Too Young to Die"; and from the Heavy Horses album, "Stairway to Heaven".
|
|
|
|