Hi ilmdaniel,

I'm struggling with a wicked headache at the moment, so I don't have
the patience to think through this at length, but I do have a few
ideas that may help you...

Your thread main-loops are quite cpu intensive and never give the OS
time to take a breather. They also call into the main thread in the
inner-loop to actually load the images, so that would seem to me to
negate the real intent of using multiple threads unless I am missing
something...

A simple way to move the file I/O into the worker thread w/o having to
scrap your current code, would just be to read data into an NSData in
your worker thread and use UIImage.LoadFromData() in your
BeginInvokeOnMainThread() delegate.

Then it just becomes a matter of throttling your worker thread loops.

I would probably also suggest merging your ShowCurrent() and
hideInvisibleImages() so that you don't have to have multiple worker
threads going, especially since they are both looping over the same
lists.

If this approach seems like it might work out, you might then consider:

1. not using a ThreadQueue, and instead consider using a long-term
worker thread.
2. making DidScroll() wake up the worker thread to continue (look at
AutoResetEvent perhaps?)
3. DidEndScrollingAnimation() wouldn't need to spawn new threads, it
could just reset the AutoResetEvent.
4. The worker thread loop could use AutoResetEvent.WaitOne() instead
of bools (and would remove the need for a Sleep() as well)


I don't know if there is something better than AutoResetEvent (there
probably is), but I don't have a lot of experience with C# thread sync
(I come from the land of C where things are a lot more painful).

Hopefully that helps...

Jeff


On Tue, Jan 31, 2012 at 3:32 PM, ilmdaniel <[email protected]> wrote:
> Hi guys,
>
> Ok, I really need your help on this one.
>
> I'm trying to use the iCarousel library in monotouch. I successfully ported
> the library, everything works perfectly but the application crashes if you
> enter too many UIImageViews with images inside, which is normal because
> iCarousel is just like a UIScrollView.
>
> I definitely have to use lazy loading system somehow from a secondary thread
> and display only 3-4 images at once but I do not know how to make this work
> smooth.
>
> At this point, I set this in the iCarousel Delegate:
>
> bool threadsAlive = true;
>
> public cDelegate()
> {
>    ThreadPool.QueueUserWorkItem( delegate { refresh_visible(); } );
> }
>
> public override void DidScroll (iCarousel carousel)
> {
>        scrolling = true;
> }
>
> public override void DidEndScrollingAnimation (iCarousel carousel)
> {
>        scrolling = false;
>        //show images that are currently on the screen
>        ThreadPool.QueueUserWorkItem( delegate { ShowCurrent();         } );
>        //hides images that are not on the screen
>        ThreadPool.QueueUserWorkItem( delegate { hideInvisibleImages(); } );
> }
>
> void refresh_visible()
> {
>        while( threadsAlive )
>        {
>                while( scrolling )
>                {
>                        ShowCurrent();
>                }
>        }
> }
>
> void refresh_hidden()
> {
>        while( threadsAlive )
>        {
>                while( scrolling )
>                {
>                        hideInvisibleImages();
>                }
>        }
> }
>
> public void ShowCurrent()
> {
>        var          ds = _carousel.DataSource as cDataSource;
>        var left_index  = _carousel.CurrentItemIndex - 1;
>        var right_index = _carousel.CurrentItemIndex + 2;
>        if( left_index  <  0 ) left_index  = 0;
>        if( right_index >= ds.Lista.Count ) right_index = ds.Lista.Count - 1;
>        //
>        for( var i = left_index; i < right_index ; i++ )
>        {
>                var img = ds.Lista[i];
>                if( img.Image == null )
>                {
>                        BeginInvokeOnMainThread( delegate{
>                                img.Image = UIImage.FromFile( 
> img.UserObject.ToString() );
>                        });
>                }
>        }
> }
>
>
> void hideInvisibleImages()
> {
>        Console.WriteLine("ascund!");
>        var          ds = _carousel.DataSource as cDataSource;
>        var left_index  = _carousel.CurrentItemIndex - 1;
>        var right_index = _carousel.CurrentItemIndex + 2;
>        if( left_index  <  0 ) left_index  = 0;
>        if( right_index >= ds.Lista.Count ) right_index = ds.Lista.Count - 1;
>        //
>        for( var i=0; i<left_index; i++ )
>        {
>                var img   = ds.Lista[i];
>                if( img.Image != null )
>                {
>                        img.Image.Dispose();
>                        img.Image = null;
>                }
>        }
>        for( var i=right_index; i<ds.Lista.Count; i++ )
>        {
>                var img   = ds.Lista[i];
>                if( img.Image != null )
>                {
>                        img.Image.Dispose();
>                        img.Image = null;
>                }
>        }
> }
>
> The code is actually very simple: there is a main thread that only shows 1
> image from the left of the current index and two images in advance, and
> another thread that cleans all other images, hides them.
>
> It's working, memory is ok, but it's not smooth on the device, it "hangs" a
> little when I scroll.  There is another way of doing this ? Or maybe I
> should change the algoritm?
>
> --
> View this message in context: 
> http://monotouch.2284126.n4.nabble.com/Lazy-loading-help-tp4345783p4345783.html
> Sent from the MonoTouch mailing list archive at Nabble.com.
> _______________________________________________
> MonoTouch mailing list
> [email protected]
> http://lists.ximian.com/mailman/listinfo/monotouch
_______________________________________________
MonoTouch mailing list
[email protected]
http://lists.ximian.com/mailman/listinfo/monotouch

Reply via email to