[Q] Making functional called in one thread run in the context ofanother?

G

Guest

Hiya

I have an JFrame-derived MainFrame class which creates a worker thread. The
thread needs to be able to call MainFrame functions, but ideally I'd like them
to be called in the context of the main application thread rather than that of
the worker thread. I guess I'm looking for a way to schedule a function call
for when the main thread is next idle.

Is there a way to achieve this?

Regards,

--Jon
 
G

Guest

Hiya

I have an JFrame-derived MainFrame class which creates a worker thread.
The thread needs to be able to call MainFrame functions, but ideally I'd
like them to be called in the context of the main application thread
rather than that of the worker thread. I guess I'm looking for a way to
schedule a function call for when the main thread is next idle.

Is there a way to achieve this?

Obviously I meant 'function' in the subject, not 'functional' :)

Regards,

--Jon
 
M

Matt Humphrey

| (e-mail address removed) wrote:
| > Hiya
| >
| > I have an JFrame-derived MainFrame class which creates a worker thread.
| > The thread needs to be able to call MainFrame functions, but ideally I'd
| > like them to be called in the context of the main application thread
| > rather than that of the worker thread. I guess I'm looking for a way to
| > schedule a function call for when the main thread is next idle.
| >
| > Is there a way to achieve this?
|
| Obviously I meant 'function' in the subject, not 'functional' :)

Shifting execution to the EDT (main GUI thread) you can use
SwingUtilities.invokeLater or invokeAndWait. It's typical for a worker
thread to pass back to the EDT upon completion to update the display, or
during operation to update status. Otherwise, if you're not updating the
GUI, the only real reason to transfer to the EDT is to avoid synchronization
problems with your application data structure. If you can describe what
you're trying to do in more detail there may be a better, more direct
solution for it. Generally, however, it's not possible to have a call
executed in a different thread unless that thread was designed with that
purpose in mind.

Matt Humphrey http://www.iviz.com/
 
G

Guest

Matt said:
| (e-mail address removed) wrote:
| > Hiya
| >
| > I have an JFrame-derived MainFrame class which creates a worker thread.
| > The thread needs to be able to call MainFrame functions, but ideally I'd
| > like them to be called in the context of the main application thread
| > rather than that of the worker thread. I guess I'm looking for a way to
| > schedule a function call for when the main thread is next idle.
| >
| > Is there a way to achieve this?
|
| Obviously I meant 'function' in the subject, not 'functional' :)

Shifting execution to the EDT (main GUI thread) you can use
SwingUtilities.invokeLater or invokeAndWait. It's typical for a worker
thread to pass back to the EDT upon completion to update the display, or
during operation to update status. Otherwise, if you're not updating the
GUI, the only real reason to transfer to the EDT is to avoid synchronization
problems with your application data structure. If you can describe what
you're trying to do in more detail there may be a better, more direct
solution for it. Generally, however, it's not possible to have a call
executed in a different thread unless that thread was designed with that
purpose in mind.

Thanks for the reply, I'll look into those functions. I'll try and describe
the issue I'm working on (please bear with me, it's a little complicated :)

I've written a java/JNI wrapper for an existing MFC program. Each MFC
function that I want to be available to java has a corresponding JNI function.

On initialisation, the java code calls a JNI method which creates a CWinThread
and starts the MFC application within it - pretty standard stuff. Since the
MFC application is running in a separate thread, each JNI function uses a
PostMessage() call to tell the MFC thread to call the appropriate function.
The JNI function are synchronous, i.e. the JNI function won't return until the
MFC program has responded to the message posted and responded appropriately.
This is necessary as the MFC code is not re-entrant.

This all works fine.

As a result of a JNI call, the MFC application may make a callback into the
java code to notify it of certain events (using GetMethodID, CallVoidMethod
and friends). Again this all works fine.

The problem comes when a callback needs to make a JNI call itself. Since the
callback occurs in the thread of the MFC application, the original synchronous
JNI call (the one that triggered the callback in the first place) has not
returned, so trying to make another JNI call will cause a deadlock :-(

Here's the problem in slightly dodgy ASCII UML:

Java JNI MFC App
| | |
| func() | |
|________\| |
| /| PostMessage() \|
| |-----------------|
| | /|
| | callback() |
|/________|_________________|
|\ | |
| |
| func2() |
|________\| Deadlock
| /|
| |


func2() is called in the context of the MFC App.

That's pretty much the crux of the problem, which made we wonder if the
callback function can schedule a function call for when the original JNI call
has finished; that way it will be executed after func() returns.

Another approach might be to avoid running the MFC application in its own
thread, and instead periodically call a dummy JNI message pump from the java
code. I don't know how responsive that would be, though, not to mention that
making repeated JNI calls could be expensive.

Regards,

--Jon
 
D

Daniel Pitts

I've written a java/JNI wrapper for an existing MFC program. Each MFC
function that I want to be available to java has a corresponding JNI
function.
Yikes! This sounds like a Bad Idea, and the Last Choice Only.
On initialisation, the java code calls a JNI method which creates a
CWinThread and starts the MFC application within it - pretty standard
stuff. Since the MFC application is running in a separate thread, each
JNI function uses a PostMessage() call to tell the MFC thread to call
the appropriate function. The JNI function are synchronous, i.e. the JNI
function won't return until the MFC program has responded to the message
posted and responded appropriately. This is necessary as the MFC code is
not re-entrant.

This all works fine. Sure it does :)

As a result of a JNI call, the MFC application may make a callback into
the java code to notify it of certain events (using GetMethodID,
CallVoidMethod and friends). Again this all works fine.

The problem comes when a callback needs to make a JNI call itself.
Since the callback occurs in the thread of the MFC application, the
original synchronous JNI call (the one that triggered the callback in
the first place) has not returned, so trying to make another JNI call
will cause a deadlock :-(

Here's the problem in slightly dodgy ASCII UML:

Java JNI MFC App
| | |
| func() | |
|________\| |
| /| PostMessage() \|
| |-----------------|
| | /|
| | callback() |
|/________|_________________|
|\ | |
| |
| func2() |
|________\| Deadlock
| /|
| |
You really should have two message queues going on here. One for the MFC
app, and one for the Java app. Alternatively, you should have your JNI
detect if its in a call already, and directly call the function instead
of using PostMessage().
func2() is called in the context of the MFC App.

That's pretty much the crux of the problem, which made we wonder if the
callback function can schedule a function call for when the original JNI
call has finished; that way it will be executed after func() returns.
You'd be better off scheduling the callback function to execute in a
different Java thread or event queue.
Another approach might be to avoid running the MFC application in its
own thread, and instead periodically call a dummy JNI message pump from
the java code. I don't know how responsive that would be, though, not
to mention that making repeated JNI calls could be expensive.
Port the original MFC program to Java. You'll get a more portable,
cleaner, and probably much less buggy program.

Good luck,
Daniel.
 
L

Lew

Matt said:
solution for it. Generally, however, it's not possible to have a call
executed in a different thread unless that thread was designed with that
purpose in mind.

To design that purpose in mind, one can use various classes from
java.util.concurrent, such as the various Executors and Queues.

Doug Lea and Brian Goetz are the authors to read.
 
M

Matt Humphrey

| Matt Humphrey wrote:
| > | > | (e-mail address removed) wrote:

<snip prelude>
|
| Thanks for the reply, I'll look into those functions. I'll try and
describe
| the issue I'm working on (please bear with me, it's a little complicated
:)
|
| I've written a java/JNI wrapper for an existing MFC program. Each MFC
| function that I want to be available to java has a corresponding JNI
function.
|
| On initialisation, the java code calls a JNI method which creates a
CWinThread
| and starts the MFC application within it - pretty standard stuff. Since
the
| MFC application is running in a separate thread, each JNI function uses a
| PostMessage() call to tell the MFC thread to call the appropriate
function.
| The JNI function are synchronous, i.e. the JNI function won't return until
the
| MFC program has responded to the message posted and responded
appropriately.
| This is necessary as the MFC code is not re-entrant.
|
| This all works fine.
|
| As a result of a JNI call, the MFC application may make a callback into
the
| java code to notify it of certain events (using GetMethodID,
CallVoidMethod
| and friends). Again this all works fine.
|
| The problem comes when a callback needs to make a JNI call itself. Since
the
| callback occurs in the thread of the MFC application, the original
synchronous
| JNI call (the one that triggered the callback in the first place) has not
| returned, so trying to make another JNI call will cause a deadlock :-(

Ok, I get all that. I'm not familiar with JNI to MFC, so let me just
confirm what I think you're saying. Are you saying that a 2nd JNI call made
from the MFC callback thread will block, but that a 2nd call made from a new
thread will not? I think you mean something slightly different, as I would
expect the 2nd call to block even when made from a separate thread. I can't
quite follow your UML ascii art, but further below I think you say that the
callback does not need to wait for the 2nd JNI call to complete. If that's
so, I think what you mean is that the 2nd call on a different thread will
block but eventually be answered asynchronously after the callback and
original JNI request have completed.

If that's the case, I think all you need to do is to create a
single-threaded executor service in your Java wrapper. You only need one of
these--don't create one each time you make a request and hang onto it for
you application.

ExecutorService executor = Executors.newSingleThreadExecutor ();

Then have your callback fire off the request

executor.submit (new Runnable () {
public void run () {
// Do your stuff here.
}
});

(To simply fire off the request in a separate thread, you can just do)
Thread t = new Thread (new Runnable () {
public void run () {
// Do your stuff here
}});
t.start ();

You don't need to wait for the executor to finish. It will simply queue up
your request and as the MFC thread becomes available each will be processed
in turn. You can check out the API to see how to manage shutdown, etc. (A
thread on its own is not guaranteed to execute in order--you may get a 2nd
request that executes before the first one.)

If the 2nd JNI call must be synchronous, I think you're SOL. I don't think
it will matter which thread it comes from, it will just block and you'll get
deadlock. I don't know how the MFC access system is designed to operate in
that regard.

| That's pretty much the crux of the problem, which made we wonder if the
| callback function can schedule a function call for when the original JNI
call
| has finished; that way it will be executed after func() returns.
|
| Another approach might be to avoid running the MFC application in its own
| thread, and instead periodically call a dummy JNI message pump from the
java
| code. I don't know how responsive that would be, though, not to mention
that
| making repeated JNI calls could be expensive.

I have systems that use hundreds of interlocked, signalling threads and I
don't have a problem with performance on that aspect. The more you can make
all requests asynchronous, the easier it becomes. For synchronous requests
you need only figure out how to respond to request completion and where to
put results. You can use the executor above to receive all requests and let
each one handle its final update itself. You'll have to decide what's
appropriate for the data structures you're trying to manage.

Cheers,
Matt Humphrey http://www.iviz.com/
 
D

Daniel Pitts

Shifting execution to the EDT (main GUI thread) you can use
SwingUtilities.invokeLater or invokeAndWait.
Actually, if you're going to use the EDT at all, its best to use
EventQueue.invoke*
SwingUtilities delegates to EventQueue.invoke*. SwingUtilities was
created because older versions of AWT didn't have an event queue, so
it delegated to a different implementation. The AWT EventQueue is
standard now, so you should use it directly.
 
L

Lew

Daniel said:
Actually, if you're going to use the EDT at all, its best to use
EventQueue.invoke*
SwingUtilities delegates to EventQueue.invoke*. SwingUtilities was
created because older versions of AWT didn't have an event queue, so
it delegated to a different implementation. The AWT EventQueue is
standard now, so you should use it directly.

For the converse, moving non-GUI actions off the EDT, there is the incomparable
<http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html>
 
R

Roedy Green

I have an JFrame-derived MainFrame class which creates a worker thread. The
thread needs to be able to call MainFrame functions, but ideally I'd like them
to be called in the context of the main application thread rather than that of
the worker thread. I guess I'm looking for a way to schedule a function call
for when the main thread is next idle.

A simple way to do it is to schedule the work packets with
invokeLater. Then will generate events that will be processed by the
Swing thread.

see http://mindprod.com/jgloss/swingthreads.html
 
G

Guest

Matt said:
| (e-mail address removed) wrote:
| > Hiya
| >
| > I have an JFrame-derived MainFrame class which creates a worker thread.
| > The thread needs to be able to call MainFrame functions, but ideally I'd
| > like them to be called in the context of the main application thread
| > rather than that of the worker thread. I guess I'm looking for a way to
| > schedule a function call for when the main thread is next idle.
| >
| > Is there a way to achieve this?
|
| Obviously I meant 'function' in the subject, not 'functional' :)

Shifting execution to the EDT (main GUI thread) you can use
SwingUtilities.invokeLater or invokeAndWait. It's typical for a worker
thread to pass back to the EDT upon completion to update the display, or
during operation to update status. Otherwise, if you're not updating the
GUI, the only real reason to transfer to the EDT is to avoid synchronization
problems with your application data structure. If you can describe what

invokeLater() does exactly what I needed, thanks!

Regards,

--Jon
 
G

Guest

Daniel said:
Yikes! This sounds like a Bad Idea, and the Last Choice Only.

I spent some time looking into methods to create java wrappers, and this way
seemed to be about the only method in use. What other approaches are there?
I need the java wrapper to be able to create and modify C++ objects that are
handled by the C++/MFC code (of course the java code doesn't interact with MFC
objects directly).

Please take my word that rewriting the whole application in java is not an
option in this case :)
You really should have two message queues going on here. One for the MFC
app, and one for the Java app. Alternatively, you should have your JNI

What exactly do you mean by 'message queue'? I'm picturing a thread that sits
and wait for tasks to be passed to it, with the calling thread waiting for the
result. Is this what you had in mind?
detect if its in a call already, and directly call the function instead
of using PostMessage().

That's an interesting idea, but looking at my code it would be a lot of work
to implement.
You'd be better off scheduling the callback function to execute in a
different Java thread or event queue.

I ended up using invokeLater() to make the callback be, um, called in the
context of the EDT. It's not a perfect solution, but it covers all the cases
I need.
>
Port the original MFC program to Java. You'll get a more portable,
cleaner, and probably much less buggy program.

See above :)
Good luck,

Thanks for your reply,

Regards,

--Jon
 

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

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top