从另一个线程填充ImageList [英] Populate an ImageList from another thread

查看:56
本文介绍了从另一个线程填充ImageList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从另一个

线程为ListView填充带有位图的ImageList,因为这是一个耗时的过程。我希望

ListViewItems''图像能够加载一个接一个,就像在Web浏览器中一样。


我编写了以下代码,但是表格冻结了,而

CreateTileBitmaps正在运行,就好像我''它在主要的

线程上完成了。如何在没有这个问题的情况下将项目添加到ImageList?

(注意:我确实*不想*使用所有者绘制ListView和Paint事件,

因为绘画标题和焦点矩形等额外的东西

太无聊了。)

private void FindTileForm_Load(object sender,EventArgs e)

{

ThreadPool.QueueUserWorkItem(new WaitCallback(CreateTileBitmaps));

}

private void CreateTileBitmaps(object notUsed)

{

foreach(tiles t in _tiles.Tiles)

{

位图bmp =新位图(32,32);

// ...做一些绘图...


lvwMatches.Invoke(

(MethodInvoker)委托{imlMatches.Images.Add(bmp) );}}

);

}

}

解决方案

< blockquote>周五,2007年12月14日17:05:54 -0800,Paul E Collins

< fi ****************** @ CL4 .orgwrote:


我想要fi从另一个

线程获取一个带有位图的ImageList,因为这是一个耗时的过程。我希望

ListViewItems''图像能够加载一个接一个,就像在Web浏览器中一样。


我编写了以下代码,但是表格冻结了,而

CreateTileBitmaps正在运行,就好像我''它在主要的

线程上完成了。如何在没有此问题的情况下将项目添加到ImageList?



嗯,你可以正确地做到这一点。这样可行。


你发布的代码中没有任何明显错误的信息,

意味着你没有发帖代码是错的。但是你必须要有一些代码

哪个错了,否则就没事了。


你应该发布一个简洁但完整的样本可靠的代码

再现了这个问题。在此期间,请参阅下面的代码示例

_does_ work(我在项目添加之间放置了2秒的延迟以使

更容易观看)。


Pete

使用System;

使用System.Collections.Generic;

使用System。 ComponentModel;

使用System.Drawing;

使用System.Text;

使用System.Windows.Forms;

使用System.Threading;


名称空间TestListViewWorkerSingleFile

{

静态类程序

{

///< summary>

///应用程序的主要入口点。

///< / summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(fals e);

Application.Run(new Form1());

}

}


公共类Form1:表格

{

public For m1()

{

InitializeComponent();

}


private void _InitListView(object obj)

{

for(int iitem = 0; iitem< 10; iitem ++)

{

位图bmpItem =新位图(32,32);

string strItem = iitem.ToString();


Thread.Sleep(2000);


使用(Graphics gfx = Graphics.FromImage(bmpItem))

{

使用(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),格式);

}

}


调用((MethodInvoker)委托( )

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


调用((MethodInvoker)委托()

{listView1.Items.Add(strItem,strItem);});

}

}


private void Form1_Load(object sender,EventArgs e)

{

listView1.LargeImageList = new ImageList();

listView1.LargeImageList.ImageSize =新尺寸(32,32);


ThreadPool.QueueUserWorkItem(_InitListView);

}


/ //< summary>

///所需的设计变量。

///< / summary>

private System.ComponentModel。 IContainer组件= null;


///< summary>

///清理正在使用的所有资源。

///< / summary>

///< param name =" disposing">如果托管资源应该是

处理,则为true;否则,false。< / param>

protected override void Dispose(bool disposing)

{

if(disposing&&( components!= null))

{

components.Dispose();

}

base.Dispose(处理);

}


#region Windows窗体设计器生成的代码


///< summary>

/// Designer支持所需的方法 - 不要使用代码编辑器修改

///此方法的内容。

/ //< / 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)

| Syst em.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


私有系统。 Windows.Forms.ListView listView1;

}

}


Peter Duniho < Np ********* @nnowslpianmk.comwrote:


嗯,你可以正确地做到。那会有用。



感谢你的代码示例和毫无意义的嘲笑。


如果我删除了你的样本锁定问题同样

Thread.Sleep调用,我的原始代码可以接受一个

Thread.Sleep调用,这似乎是个问题。我不明白

为什么需要它。


我也注意到ImageList.Items.AddRange比

多次调用Add,所以我会分组传递位图而不是

一次一个。


Eq。


2007年12月14日星期五18:27:21 -0800,Paul E Collins

< fi ******** **********@CL4.orgwrote:


" Peter Duniho" < Np ********* @nnowslpianmk.comwrote:


>嗯,你可以正确地做到这一点。那会有用。



感谢您的代码示例和毫无意义的嘲笑。



没有嘲笑在我的帖子中。


如果我删除了

Thread.Sleep调用和我的原始代码,你的样本会遇到同样的问题。用一个

Thread.Sleep调用可以接受,这似乎是个问题。我不明白

为什么需要它。



我也不是。无论是否有电话,我的电脑都能正常工作

睡觉()。


无论如何,你仍然没有发布代码示例这将允许

任何人帮助建议你。鉴于与计算机相比,行为与

的明显不同,您可能还应具体说明您已经安装的.NET版本是什么以及您使用的是什么操作系统使用。没有这一切,我认为你不会得到真正的答案。


Pete


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); }
);
}
}

解决方案

On Fri, 14 Dec 2007 17:05:54 -0800, Paul E Collins
<fi******************@CL4.orgwrote:

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;
}
}


"Peter Duniho" <Np*********@nnowslpianmk.comwrote:

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.


On Fri, 14 Dec 2007 18:27:21 -0800, Paul E Collins
<fi******************@CL4.orgwrote:

"Peter Duniho" <Np*********@nnowslpianmk.comwrote:

>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


这篇关于从另一个线程填充ImageList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆