我正在尝试创建一个FileViewer控件,在我将List(文件名与图标,大小等)添加到我的ListView(图标 - 文件名 - 扩展名 - 大小)后,我还检查文件是否是image(png / jpg等),但这是我在不同的线程上做的。
我对线程的期望是它在主应用程序旁边运行,但是在我添加了所有文件后,我启动了这个线程。它会检查ListView中的所有文件并为它们创建缩略图。如果正确完成,ListView图标应该在加载时一个接一个地出现 - 但它们不是。它们都出现在同一时间。
......当线程处于活动状态时,我无法做任何事情。
为什么会发生这种情况,我做错了什么?我以前处理过Threads并且它始终有效,我用Callback调用该方法。
线程流程:
全部在一个帖子中完成。
private void GetFiles()
{
// Load all files in directory
Thread t = new Thread(new ThreadStart(GetImageFiles));
t.Priority = ThreadPriority.Lowest;
t.Start();
}
delegate void GetImageFilesCallback();
private void GetImageFiles()
{
if (this.IsHandleCreated)
{
if (files.InvokeRequired)
{
GetImageFilesCallback callback = new GetImageFilesCallback(GetImageFiles);
this.Invoke(callback);
}
else
{
string extension = "";
string key = "";
foreach (string file in _files)
{
extension = FileManager.GetExtension(file);
key = (DirectoryCurrent + file).Replace(":", "").Replace("\\", "_").Replace(".", "_");
foreach (string knownimages in _knownImageTypes)
{
if (extension.ToLower() == knownimages)
{
foreach (ListViewItem item in files.Items)
{
if (item.Text == file)
{
if (files.SmallImageList != null)
{
if (files.SmallImageList.Images[key] == null)
{
files.SmallImageList.Images.Add(key, Image.FromFile(DirectoryCurrent + file).GetThumbnailImage(16, 16, null, IntPtr.Zero));
files.LargeImageList.Images.Add(key, Image.FromFile(DirectoryCurrent + file).GetThumbnailImage(32, 32, null, IntPtr.Zero));
}
files.Items[item.Index].ImageKey = key;
}
}
}
}
}
}
files.Refresh();
}
}
}
答案 0 :(得分:1)
您的线程调用的方法是在主线程上调用自己,然后在该线程中执行所有工作,从而阻止您的UI。
您应该安排代码,以便线程代码不会触及ListView,只是加载每个图像,然后调用主线程方法,传递位图,以便主线程可以将它们分配给ListView。
这是我的意思草图:
// this is your thread method
// it touches no UI elements, just loads files and passes them to the main thread
private void LoadFiles(List<string> filenames) {
foreach (var file in filenames) {
var key = filename.Replace(...);
var largeBmp = Image.FromFile(...);
var smallBmp = Image.FromFile(...);
this.Invoke(new AddImagesDelegate(AddImages), key, largeBmp, smallBmp);
}
}
// this executes on the main (UI) thread
private void AddImages(string key, Bitmap large, Bitmap small) {
// add bitmaps to listview
files.SmallImageList.Images.Add(key, small);
files.LargeImageList.Images.Add(key, large);
}
private delegate AddImagesDelegate(string key, Bitmap large, Bitmap small);
答案 1 :(得分:0)
阅读以下内容:http://www.codeproject.com/Articles/10311/What-s-up-with-BeginInvoke。 Invoke和BeginInvoke的重要一点是它们都在主线程上运行。 BeginInvoke只是在返回控件之前不等待处理消息。但最终,工作将在主线程上发生,并将阻塞直到完成。