Moody
Moody

Reputation: 25

FREBitmapData.relase throws FREWrongThreadException

I'm trying to build an ane who take an empty bitmap

bitmapData  = new BitmapData(size.width,size.height,false, 0x00000000);

acquire it, edit the bytebuffer in a different thread then release it.

Here's the call function code in the java part

public FREObject call(FREContext freContext, FREObject[] args) {
        try {
            FREBitmapData bitmapData = (FREBitmapData)args[0];
            bitmapData.acquire();       
            ByteBuffer bytebuffer = 
            myTaskProcessingQueue.put(new Task(freContext,bitmapData,bytebuffer)); //edit the bitmap data in a specific thread
        } catch (InterruptedException e) {
           Log.e(TAG, "exception", e);
        } catch (FREInvalidObjectException e) {
            Log.e(TAG, "exception", e);
        } catch (FREWrongThreadException e) {
            Log.e(TAG, "exception", e);
        }
        return null;
    }

And when I'm done with the bytebuffer :

new Handler(Looper.getMainLooper()).post(new Runnable () {
                @Override
                public void run () {
                    try {                    
                        Toast.makeText(task.context.getActivity(),"Toast",Toast.LENGTH_SHORT).show();             
                        task.bitmapData.release();
                    } catch (FREInvalidObjectException e) {
                        Log.e("InitExtractorFunction", "FREInvalidObjectException", e);
                    } catch (FREWrongThreadException e) {
                        Log.e(TAG, "exception", e);
                    }
                }
            });

The toast instruction works fine, but the bitmapData.release() one throws a FREWrongThreadException even though I am on the main thread, and I can't find any documentation about this exception on the adobe website.

Any idea?

Edit :

Here's more code for the thread class where i'm editing the data :

private class MyTaskWorker extends Thread {


    @Override
    public void run() {

        while (true) {
            try {
                processMyTask(myTaskProcessingQueue.take());


            } catch (InterruptedException e) {
                Log.e(TAG,"InterruptedException", e);
            }
        }
    }

    private void processMyTask(Task task) {

            // do work with bytebuffer


            new Handler(Looper.getMainLooper()).post(new Runnable () {
                @Override
                public void run () {
                    try {

                        Log.d(TAG, "Thread: " + Thread.currentThread().getName());
                        Toast.makeText(task.context.getActivity(),"Toast",Toast.LENGTH_SHORT).show();

                        task.bitmapData.release();

                        Log.i(TAG,"bitmap released");
                    } catch (FREInvalidObjectException e) {
                        Log.e(TAG, "FREInvalidObjectException", e);
                    } catch (FREWrongThreadException e) {
                        Log.e(TAG,"FREWrongThreadException", e);
                    }
                }
            });





    }

}

Edit 2 :

I also tried to do both the acquire and the relase in the same background thread and still no dice. The only way I managed to make it work is when I do both the acquire and the release inside the call function, but I don't want to block the main thread to wait for the bitmap modification...

Upvotes: 0

Views: 60

Answers (1)

Nick Cardoso
Nick Cardoso

Reputation: 21733

Just like regular multithreading, whenever you acquire a lock, it must be released by the same thread who locked it.

The documentation for this exception has the following description:

FRE_WRONG_THREAD The method was called from a thread other than the one on which the runtime has an outstanding call to a native extension function.

Thus when call() is called from a background thread, the background thread is the one that locks bitmapData, which means the main thread does not own the lock to release it later.

You can always test this by logging the thread name in each location:

Log.d(..., "Thread: " + Thread.currentThread().getName());

The solution will be to ensure that the release() method is invoked from the same place (thread) as call() (wherever this may be)

Upvotes: 0

Related Questions