InvokeRequired? (multithreading)

J

Julie

It looks to me like InvokeRequired() is returning an unexpected
result.

I have a multi-threaded app, and know it's a good idea to put all
functionality related to a Windows Forms control on the same thread.

I have a class which inherits from Form. When I construct an object of
this class, I print out the value for
Thread.CurrentThread.ManagedThreadId.

In all of the functions in my class, I have the same structure:

public delegate void functionNameCallback();
public void functionName()
{
if (this.InvokeRequired)
{
functionNameCallback e = new functionNameCallback(functionName);
this.Invoke(e, null);
}
else
{
// print value of Thread.CurrentThread.ManagedThreadId here
....
// do whatever work here
}
}

I can see that the thread that is calling the function is getting
"InvokeRequired" set to false; therefore, it is just doing the work
without invoking. The value for Thread.CurrentThread.ManagedThreadId
printed in the function does not match the value printed in the
constructor.

What's going on???
 
M

Mike Lovell

Julie said:
It looks to me like InvokeRequired() is returning an unexpected
result.

I have a multi-threaded app, and know it's a good idea to put all
functionality related to a Windows Forms control on the same thread.

I have a class which inherits from Form. When I construct an object of
this class, I print out the value for
Thread.CurrentThread.ManagedThreadId.

In all of the functions in my class, I have the same structure:

public delegate void functionNameCallback();
public void functionName()
{
if (this.InvokeRequired)
{
functionNameCallback e = new functionNameCallback(functionName);
this.Invoke(e, null);
}
else
{
// print value of Thread.CurrentThread.ManagedThreadId here
....
// do whatever work here
}
}

I can see that the thread that is calling the function is getting
"InvokeRequired" set to false; therefore, it is just doing the work
without invoking. The value for Thread.CurrentThread.ManagedThreadId
printed in the function does not match the value printed in the
constructor.

What's going on???

Might be of help:

http://www.gotinker.com/2010/03/09/dont-shoot-the-messenger-dont-hang-the-ui/

If you're calling the function from the main thread, and at that point
checking if "InvokeRequired" (which I see you're doing) will indeed be
false. Invoke isn't required at that point. I always put my background
work in a separate thread, then use the dispatcher to talk back to the
control. I don't even bother checking InvokeRequired, because it's always
required (the way I do things!).
 
P

Peter Duniho

Julie said:
[...]
I can see that the thread that is calling the function is getting
"InvokeRequired" set to false; therefore, it is just doing the work
without invoking. The value for Thread.CurrentThread.ManagedThreadId
printed in the function does not match the value printed in the
constructor.

What's going on???

Without a concise-but-complete code example, impossible to say. You
might be displaying the wrong information, or it could be that your
class really is created on a different thread. The thread that's
important is the one where the Form sub-class is shown, not where it's
instantiated.

Normally, yes…the thread ID should be the same when InvokeRequired is
false. But depending on what your code really does, you may or may not
see the same output from each location in the code.

Pete
 
J

Julie

Might be of help:

http://www.gotinker.com/2010/03/09/dont-shoot-the-messenger-dont-hang...

If you're calling the function from the main thread, and at that point
checking if "InvokeRequired" (which I see you're doing) will indeed be
false.  Invoke isn't required at that point.  I always put my background
work in a separate thread, then use the dispatcher to talk back to the
control.  I don't even bother checking InvokeRequired, because it's always
required (the way I do things!).

--
Mike
GoTinker, C# Bloghttp://www.gotinker.com- Hide quoted text -

- Show quoted text -

Darn, I'm at work, and that website you pointed me to hasn't been
"approved" for us to go to. Any chance you could post an excerpt of it
directly on your reply? Thanks!
 
M

Mike Lovell

Darn, I'm at work, and that website you pointed me to hasn't been
"approved" for us to go to. Any chance you could post an excerpt of it
directly on your reply? Thanks!

But they let you get to newsgroups? :blush:) Odd!

Excuse the formatting:

public partial class MainWindow : Window
{
private Thread workerThread;


public MainWindow()
{
InitializeComponent();
}


private void SetButtonsIsEnabled(bool value)
{
buttonStartRight.IsEnabled = value;
buttonStartWrong.IsEnabled = value;
}


private void buttonStartWrong_Click(object sender, RoutedEventArgs e)
{
SetButtonsIsEnabled(false);

for (int i=0; i<100; i+= 10)
{
Thread.Sleep(1000);

progress.Value = (double)i;
}

SetButtonsIsEnabled(true);
}


private void buttonStartRight_Click(object sender, RoutedEventArgs e)
{
SetButtonsIsEnabled(false);

workerThread = new Thread(new ThreadStart(delegate()
{
for (int i=0; i<100; i+= 10)
{
Thread.Sleep(1000);

Dispatcher.BeginInvoke((MethodInvoker)delegate()
{
progress.Value = (double)i;
}, null);
}

Dispatcher.BeginInvoke((MethodInvoker)delegate()
{
SetButtonsIsEnabled(true);
}, null);
}));

workerThread.Start();
}
}
 
J

Julie

Julie said:
[...]
I can see that the thread that is calling the function is getting
"InvokeRequired" set to false; therefore, it is just doing the work
without invoking. The value for Thread.CurrentThread.ManagedThreadId
printed in the function does not match the value printed in the
constructor.
What's going on???

Without a concise-but-complete code example, impossible to say.  You
might be displaying the wrong information, or it could be that your
class really is created on a different thread.  The thread that's
important is the one where the Form sub-class is shown, not where it's
instantiated.

Normally, yes…the thread ID should be the same when InvokeRequired is
false.  But depending on what your code really does, you may or may not
see the same output from each location in the code.

Pete

Okay, this is helpful: "The thread that's
important is the one where the Form sub-class is shown, not where it's
instantiated."

So, are you saying that the thread which calls SubClass.Show()?

Basically, I have one thread (thread A) which handles my main GUI.
Thread B comes along and calls Thread A to construct a new SubClass.
Thread B calls my function SubClass.draw() which returns
InvokeRequired = false, so Thread B resizes/repositions the GUI and
shows it. Thread B then makes additional calls to add text to the GUI
(and once again InvokeRequired = false), so Thread B adds the text
itself.

Does this sound okay?
 
J

Julie

Okay, I was having problems with what I was doing (above). I think it
seems to be working pretty well now.

I modified it so that:
Thread B comes along and calls Thread A to construct a new SubClass.
****Thread A then calls SubClass.show() so that Thread A now owns the
SubClass object.***
Then Thread B later calls SubClass.functionName(), which causes
InvokeRequired = true, which causes Thread A to do the work.

Sorry, maybe in the future I will modify this so as to not use the
methodology of InvokeRequired, but for now, I'm just happy that this
works. :blush:)

Thanks for your help, you guys.
 

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