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
