TechTalkz.com Logo

Go Back   TechTalkz.com Technology & Computer Troubleshooting Forums > Tech Support Archives > Programing Languages > C#(C Sharp)

Notices

Reply
 
Thread Tools Display Modes
Old 15-12-2007, 07:22 AM   #1
Paul E Collins
Guest
 
Posts: n/a
Populate an ImageList from another thread

I want to fill an ImageList with bitmaps for a ListView from another
thread, because it's a time-consuming process. I expect the
ListViewItems' images to "load" one by one, as in a Web browser.

I wrote the following code, but the form freezes up while
CreateTileBitmaps is running, just as if I'd done it on the main
thread. How can I add items to the ImageList without this problem?
(Note: I do *not* want to use an owner-draw ListView and Paint events,
because painting the extra things like captions and focus rectangles
is too tiresome.)


private void FindTileForm_Load(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(CreateTileBitmaps));
}


private void CreateTileBitmaps(object notUsed)
{
foreach (Tile t in _tiles.Tiles)
{
Bitmap bmp = new Bitmap(32, 32);
// ... do some drawing ...

lvwMatches.Invoke(
(MethodInvoker) delegate { imlMatches.Images.Add(bmp); }
);
}
}


  Reply With Quote
Old 15-12-2007, 08:25 AM   #2
Peter Duniho
Guest
 
Posts: n/a
Re: Populate an ImageList from another thread

On Fri, 14 Dec 2007 17:05:54 -0800, Paul E Collins
<find_my_real_address@CL4.org> wrote:

> I want to fill an ImageList with bitmaps for a ListView from another
> thread, because it's a time-consuming process. I expect the
> ListViewItems' images to "load" one by one, as in a Web browser.
>
> I wrote the following code, but the form freezes up while
> CreateTileBitmaps is running, just as if I'd done it on the main
> thread. How can I add items to the ImageList without this problem?


Well, you could do it correctly. That would work.

There's nothing obvious in the code that you posted that's wrong, which
means you didn't post the code that's wrong. But you must have some code
somewhere that's wrong, otherwise it would be fine.

You should post a concise-but-complete sample of code that reliably
reproduces the problem. In the meantime, see below for an example of code
that _does_ work (I put a 2-second delay in between item additions to make
it easier to watch).

Pete


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace TestListViewWorkerSingleFile
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(fals e);
Application.Run(new Form1());
}
}

public class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void _InitListView(object obj)
{
for (int iitem = 0; iitem < 10; iitem++)
{
Bitmap bmpItem = new Bitmap(32, 32);
string strItem = iitem.ToString();

Thread.Sleep(2000);

using (Graphics gfx = Graphics.FromImage(bmpItem))
{
using (Font font = new Font(Font.FontFamily,
Font.SizeInPoints * 1.1f, FontStyle.Bold))
{
SizeF szf = gfx.MeasureString(strItem, font);
StringFormat format = new StringFormat();

format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
gfx.DrawString(strItem, font, Brushes.Black, new
RectangleF(0, 0, 32, 32), format);
}
}

Invoke((MethodInvoker)delegate()
{ listView1.LargeImageList.Images.Add(strItem, bmpItem); });

Invoke((MethodInvoker)delegate()
{ listView1.Items.Add(strItem, strItem); });
}
}

private void Form1_Load(object sender, EventArgs e)
{
listView1.LargeImageList = new ImageList();
listView1.LargeImageList.ImageSize = new Size(32, 32);

ThreadPool.QueueUserWorkItem(_InitListView);
}

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be
disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.listView1 = new System.Windows.Forms.ListView();
this.SuspendLayout();
//
// listView1
//
this.listView1.Anchor =
((System.Windows.Forms.AnchorStyles)((((System.Win dows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView1.Location = new System.Drawing.Point(13, 13);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(267, 241);
this.listView1.TabIndex = 0;
this.listView1.UseCompatibleStateImageBehavior = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.listView1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.ListView listView1;
}
}
  Reply With Quote
Old 15-12-2007, 08:26 AM   #3
Paul E Collins
Guest
 
Posts: n/a
Re: Populate an ImageList from another thread

"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote:

> Well, you could do it correctly. That would work.


Thanks for your code sample and meaningless sneering.

Your sample has the same problem with locking up if I remove the
Thread.Sleep call, and my original code works acceptably with a
Thread.Sleep call, so that seems to be the issue. I don't understand
why it is required.

I also noticed that ImageList.Items.AddRange is a *lot* faster than
several calls to Add, so I'll pass the bitmaps in groups instead of
one at a time.

Eq.


  Reply With Quote
Old 15-12-2007, 09:12 AM   #4
Peter Duniho
Guest
 
Posts: n/a
Re: Populate an ImageList from another thread

On Fri, 14 Dec 2007 18:27:21 -0800, Paul E Collins
<find_my_real_address@CL4.org> wrote:

> "Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote:
>
>> Well, you could do it correctly. That would work.

>
> Thanks for your code sample and meaningless sneering.


There was no "sneering" in my post.

> Your sample has the same problem with locking up if I remove the
> Thread.Sleep call, and my original code works acceptably with a
> Thread.Sleep call, so that seems to be the issue. I don't understand
> why it is required.


I don't either. Mine works fine on my computer with or without the call
to Sleep().

In any case, you still haven't posted a code sample that would allow
anyone to help advise you. Given the apparent difference in behavior with
respect to the computer, you should probably also be specific about what
version of .NET you have installed and what OS you're using. Without all
of that, I don't think you're going to get a real answer.

Pete
  Reply With Quote
Old 15-12-2007, 10:58 AM   #5
Greg Cadmes
Guest
 
Posts: n/a
Re: Populate an ImageList from another thread

On Dec 14, 5:05 pm, "Paul E Collins" <find_my_real_addr...@CL4.org>
wrote:
> I want to fill an ImageList with bitmaps for a ListView from another
> thread, because it's a time-consuming process. I expect the
> ListViewItems' images to "load" one by one, as in a Web browser.
>
> I wrote the following code, but the form freezes up while
> CreateTileBitmaps is running, just as if I'd done it on the main
> thread. How can I add items to the ImageList without this problem?
> (Note: I do *not* want to use an owner-draw ListView and Paint events,
> because painting the extra things like captions and focus rectangles
> is too tiresome.)
>
> private void FindTileForm_Load(object sender, EventArgs e)
> {
> ThreadPool.QueueUserWorkItem(new WaitCallback(CreateTileBitmaps));
>
> }
>
> private void CreateTileBitmaps(object notUsed)
> {
> foreach (Tile t in _tiles.Tiles)
> {
> Bitmap bmp = new Bitmap(32, 32);
> // ... do some drawing ...
>
> lvwMatches.Invoke(
> (MethodInvoker) delegate { imlMatches.Images.Add(bmp); }
> );
> }
>
>
>
> }- Hide quoted text -
>
> - Show quoted text -



You can't simply call lvwMatches.Invoke. Try lvwMatches.BeginInvoke.
Fire and forget...

Greg
  Reply With Quote
Reply

Thread Tools
Display Modes


Google
 


All times are GMT +5.5. The time now is 06:33 AM.


vBulletin, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO
Copyright © 2005-2008, TechTalkz.com. All Rights Reserved - Privacy Policy
Valid XHTML 1.0 Transitional