tags:

views:

394

answers:

10

I have a certain application which feeds information into an object, after comparing the new information to the old information. It goes something like

set
{
    oldval=_value;
    _value=value;
    if (some comparison logic)
     raiseEvent();
}

This all happens on a background thread, in an infinite loop, which intermittently sleeps for 100ms. The really odd part is that it works the first time, the comparison logic turns up true, and the event is raised. After that, the information keeps flowing, it keep entering the object, I know this because I set MessageBoxes to display the old and new values all the time, but its as if it somehow bypasses the set clause! I set a messagebox in the beginning of the clause, an it just doesn't pop up! This is really wierd, since I am sure that the value keeps updating.

Any Thoughts?

+1  A: 

You really need to give more information. All we've got here is some pseudocode. Try to come up with a short but complete program that demonstrates the problem.

Jon Skeet
+5  A: 

Without some meaningful code, we can only guess. In particular, if adding a MessageBox to the start of the Set doesn't appear, then it is likely that the problem is at the calling code (not this).

Some thoughts, though - especially since you have multiple threads:

  • is there a thread race somewhere? should some of the code be synchronized?
  • has the worker got a stale copy of a non-volatile value?
  • thread affinity: is something involving the worker and the UI borking things?
  • are you sure you have the right instance (i.e. is it possible that the object firing the event isn't the same object you were listening for)?

It could be none of these; without some example code we can't really help.

I've marked thread affinity in bold, as this is a very likely problem if your worker is making changes that (via an event) the UI is listening for; the UI event-handler must switch to the UI thread to update the UI:

void SomeHandler(object sender, EventArgs args)
{
    this.Invoke((MethodInvoker)delegate {
       this.Text = "Something happened";
    });
}
Marc Gravell
+2  A: 

Previous answers are totally right in that you need to provide more information.

But can I ask why you are doing it like this? Surely your business model would just raise an event when the value is set, why is there a background thread running to intermittently check?

Maybe I am just missing something, but it just seems that there is likely a design flaw here that is causing the real issue.

Rob Cooper
It sounds like the worker is *supplying* the changes, not watching for them. Which is why I'm especially worried about thread-affinity.
Marc Gravell
A: 

Yeah, I know, but unfortunately theres not much more I can show... Let me try to explain the overall structure again: I have a separate background thread running an infinite loop. This loop continuously pulls data from a Data object, which is updated by a whole other set of threads. All of this is of course under synchronization with Monitor.Enter and Exit. The data pulled from the Data object is then inputted into the Comparer object.

while(true)
{
    Thread.Sleep(100);
    Monitor.Enter(Data);
    Comparer.Value = Data.Value;
    Monitor.Exit(Data);
}

The Comparer.Value is the property I mentioned in the first post. Its really quite weird since I set up a MessageBox in the end of the loop:

MessageBox.Show(Comparer.Value + " - " + Data.Value);

and the values DO actually update, it just somehow seems to bypass the set clause, which is impossible... This is truly weird.

And Rob, the loop doesn't do any of the checking, it just simulates a stream of information into Comparer.Value; It's set clause contains the comparison logic.

bh213, I'm pretty that it is, but I can't tell because the comparison stops before any meaningful checking is done.

What makes you think the set is bypassed? I'm really leaning towards thread affinity here... I've updated my post to show more...
Marc Gravell
For one thing you should be using the lock statement or putting the Monitor.Exit call in a finally block - otherwise you'll "leak" a lock if the Comparer.Value = Data.Value throws an exception.
Jon Skeet
A: 

Since event is being raised on background thread all your event handlers are being run on that (background) thread. Is your code handling this correctly?

bh213
A: 

As others said, you really need to create a small working example to show the problem.

Probably you will even notice the source of your problem yourself while you create this sample app.

Sam
A: 

Marc, its not the UI thread thats being updated, its another background thread. The thread layout is as such: Several Worker threads input > Data.Value which is then outputted intermittently > Comparer.Value.

I'm really struggling with this one since I'm pretty confident its not a problem with the threads, and I don't have half-a-clue what it could be... Something with the set clause is not right.

No; you can't update to another background thread, as there is no sync-context (i.e. no way of calling this.Invoke). The problem here is that you haven't shown any of the code (even pesudo code) for the code that is showing the symptom (which you also haven't described).
Marc Gravell
Or another way: what (code) makes you think there is a problem? What code is having a problem?
Marc Gravell
To clarify: another thread can (of source) access state via properties etc: I just mean that you can't push the event so that it executes on the *other* worker...
Marc Gravell
+2  A: 

Spam System.Diagnostic.Debug.WriteLine around instead of messageboxes. These do not (or at least they do only to a minimum) change the instruction flow and have no threading issues (apart possible bad output).

Also, from the description, it seems a simple debug session with some carefully placed breakpoint might help.

Third, what is the "(some comparison logic)" ?

If it is a simple (oldval != _value) rewrite it as

set
{
 if (_value != value)
 {
  _value=value;
  RaiseSomeEvent();
 }
}

it's cleaner and you have no chance of _value changing without the event being raised (apart no subscribed handlers..).

Otherwise the "(some comparison logic)" expression is likely the bugged location.

Marco M.
A: 

Marco, the comparison logic refers to something else - to whether or not the leap in value is larger than X. And again, its not the comparison logic thats bugged, since it works once and then stops. I'm pretty sure it doesn't even reach that point after the first run, since the MessageBox in the very beginning of the set clause doesn't even pop up.

And I don't understand, what does System.Diagnostics.Debug.WriteLine do?

A: 

Alright, I've solved the problem, apparently my question was wrong, the problem was in a whole other place. Thanks for all the help, the question may be closed.