线程使应用程序停止

时间:2012-09-13 23:04:43

标签: c# multithreading file callback

我正在尝试创建一个FileViewer控件,在我将List(文件名与图标,大小等)添加到我的ListView(图标 - 文件名 - 扩展名 - 大小)后,我还检查文件是否是image(png / jpg等),但这是我在不同的线程上做的。

我对线程的期望是它在主应用程序旁边运行,但是在我添加了所有文件后,我启动了这个线程。它会检查ListView中的所有文件并为它们创建缩略图。如果正确完成,ListView图标应该在加载时一个接一个地出现 - 但它们不是。它们都出现在同一时间。

......当线程处于活动状态时,我无法做任何事情。

为什么会发生这种情况,我做错了什么?我以前处理过Threads并且它始终有效,我用Callback调用该方法。

线程流程:

  1. 格式文件密钥=“C:\ image.png”=“C_image_png”。
  2. 检查图像的缩略图是否存在(通过检查它的键),然后使用它
  3. Else使用Image.FromFile()加载缩略图.GetThumbnailImage()并使用Key将图像添加到Listview的图像
  4. 最后更改ListView项目的ImageKey。
  5. 全部在一个帖子中完成。

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

2 个答案:

答案 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只是在返回控件之前不等待处理消息。但最终,工作将在主线程上发生,并将阻塞直到完成。