B4i Library Background Task - Run a Sub in background thread without blocking the UI (Asynchronous)

JackKirk

Well-Known Member
Licensed User
Longtime User
Narek,

What a potentially fascinating bit of code.

I am trying to use it to extract "brightness" from a bitmap.

I get an error dump:
B4X:
Unexpected event (missing RaisesSynchronousEvents): event_bc_scanner_stillimage_background:
Error occurred on line: 561 (ZXBarcodeScanner)
-[UIImage object]: unrecognized selector sent to instance 0x155902c0
Stack Trace: (
  CoreFoundation       <redacted> + 150
  libobjc.A.dylib      objc_exception_throw + 38
  CoreFoundation       <redacted> + 0
  CoreFoundation       <redacted> + 700
  CoreFoundation       _CF_forwarding_prep_0 + 24
  my24-7laundry        -[b4i_zxbarcodescanner _event_bc_scanner_stillimage_background::] + 832
  CoreFoundation       <redacted> + 68
  CoreFoundation       <redacted> + 292
  my24-7laundry        +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1786
  my24-7laundry        -[B4IShell runMethod:] + 574
my24-7laundry        -[B4IShell raiseEventImpl:method:args::] + 1998
my24-7laundry        __40-[B4IShell raiseEventImpl:method:args::]_block_invoke + 38
libdispatch.dylib    <redacted> + 10
libdispatch.dylib    <redacted> + 22
libdispatch.dylib    <redacted> + 1524
CoreFoundation       <redacted> + 8
CoreFoundation       <redacted> + 1574
CoreFoundation       CFRunLoopRunSpecific + 520
CoreFoundation       CFRunLoopRunInMode + 108
GraphicsServices     GSEventRunModal + 160
UIKit                UIApplicationMain + 144
my24-7laundry        main + 108
libdyld.dylib        <redacted> + 2
)

When I put the following code in the background task:
B4X:
559 'Extract bitmap to a byte array
560 Private no As NativeObject = Me
561 Private bmp_bytes() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(Image)))    '<<<<<< fails here

If I do the bitmap to byte array conversion outside the background task and pass the byte array to the background task all seems to work fine.

I take it that the bitmap is considered UI? - it isn't really.

The main reason for looking at backgrounding the "brightness" extraction is because the bitmap to byte array conversion is a cycle gobbler.

Any comments or suggestions welcome.

Thanks in anticipation...
 

narek adonts

Well-Known Member
Licensed User
Longtime User

it is strange.

Try to create a Sub like this

B4X:
Sub GetByteFromBitmap(img As Bitmap, Quality As Int) As Byte()
      Dim out As OutputStream
      Dim data() As Byte
      out.InitializeToBytesArray(1)
      img.WriteToStream(out,Quality,"JPEG")
      data = out.ToBytesArray
      out.Close
      Return data

' credits to jaraiza

End Sub

and use this sub in your backgroundTask

Narek
 

narek adonts

Well-Known Member
Licensed User
Longtime User
I think I found the issue. There is problem passing parameters with the Class.


Try this

B4X:
Sub GetByteFromBitmap(img As Object, Quality As Int) As Byte()
      Dim out As OutputStream
      Dim data() As Byte
      out.InitializeToBytesArray(1)
      Dim tmpImg as Bitmap=img
      tmpImg.WriteToStream(out,Quality,"JPEG")
      data = out.ToBytesArray
      out.Close
      Return data

' credits to jaraiza

End Sub


Or post your Background Sub and I will correct it.

The issue is that you should declare the parameters as Object (for bitmap).
 
Last edited:

narek adonts

Well-Known Member
Licensed User
Longtime User
For your issue if you will change the parameter part (Image as Bitmap) to (Image as Object) and after

Dim tmpImg as Bitmap=Image

Private no As NativeObject = Me
Private bmp_bytes() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(tmpImg))) it should work
 

JackKirk

Well-Known Member
Licensed User
Longtime User
Narek,

That did the trick - now working beautifully.

Many Thanks...
 

JackKirk

Well-Known Member
Licensed User
Longtime User
What a potentially fascinating bit of code.
Narek,

I have changed my assessment to "what an unequivocally brilliant bit of code".
 

JackKirk

Well-Known Member
Licensed User
Longtime User
Narek,

Looking at your latest version of your class at post #1, I notice in the Objective C:

-(void)RunThread4: ...

but RunThread4 doesn't seem to be used anywhere - am I missing something?

Regards...
 

JackKirk

Well-Known Member
Licensed User
Longtime User
Narek,

Maybe a little tip for others using your class...

When running your class in my project in DEBUG mode I get a series of non-fatal log messages of the form:

Unexpected event (missing RaisesSynchronousEvents): ...

I have found I can suppress these messages by wrapping the initiation of the background task like so:
B4X:
#IF RELEASE
 
    'Process task in background
    myBGTask.Initialize("MyTask",Me,Array(yourParam))

#ELSE
 
    'Process task in foreground
    MyTask(yourParam)

#END IF


and placing the following as the last statements in MyTask:
B4X:
#IF RELEASE

    'Do nothing - MyTask_Done will be automatically fired by myBGTask

#ELSE

    'Complete processing MyTask in foreground
    MyTask_Done

#END IF
Regards...
 
Last edited:

JackKirk

Well-Known Member
Licensed User
Longtime User
myBGTask.Initialize("MyTask",Me,Array(Null))
Narek,

The above does not work, this does:

myBGTask.Initialize("MyTask",Me,Array())

Suggest you change the 2 references in your post #1 to reflect this.

Also, if you are editing your post #1 you might like to change:

Run a Sub in Background thread (without blocking th UI).

to

Run a Sub in Background thread (without blocking the UI).

I know, I know, I am a picky pedantic bastard, but your class deserves full polish.

I continue to be awed - it would appear that not only can I process an image in the background but I can also capture it there.

Regards...
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…