将项添加到ObservableCollection时,UI线程冻结

时间:2016-03-11 18:25:05

标签: c# multithreading

在下面的代码中我将一些图像转换为另一个线程上的二进制格式,但是我的UI线程仍然冻结,它应该只显示每个转换后的项目(保存ByteImage的ObservableCollection)。

在UI线程有时间将每个对象添加到ObservableCollection之前,似乎正在转换图像!

有什么问题?我注意到如果我添加Sleep(4)它会平滑地显示图像。

Task.Factory.StartNew(() =>
                {
                    // Generate List of images to upload
                    var files = Directory.EnumerateFiles(sel.Name, "*.*", SearchOption.AllDirectories)
                        .Where(s => s.EndsWith(".jpeg") || s.EndsWith(".jpg") || s.EndsWith(".png"));
                    int b = 0;

                    if (files.Count() > 0)
                    {
                        foreach (string item in files)
                        {
                            // Generate new name
                            string oldname = Path.GetFileNameWithoutExtension(item);
                            string newName = Common.Security.KeyGenerator.GetUniqueKey(32);
                            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                Filenames.Add(
                                    new NFile
                                    {
                                        OldName = oldname,
                                        NewName = newName
                                    });
                            }));

                        }

                        // Manage each image
                        foreach (string item in files)
                        {
                            // Generate thumbnail byte array
                            var img = GenerateThumbnailBinary(item);

                            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                UploadProgress = (int)Math.Round((double)(100 * b / files.Count()));
                                Thumbnails.Add(new ByteImage { Image = img });
                            }));
                            b++;

                            //System.Threading.Thread.Sleep(40);
                        }
                    }
                });

编辑: 我现在收到以下错误,我假设我只是设置了我要添加到任务线程的一行代码?然后当它完成时执行Dispatcher?

错误: 严重性代码描述项目文件行

  

非静态字段,方法或者需要对象引用   property'Dispatcher.Invoke(Action)'

代码:

// Manage each image
ByteImage img = new ByteImage();
foreach (string item in files)
{
    // Generate thumbnail byte array
    var task = Task.Run(() =>
    {
        img.Image = GenerateThumbnailBinary(item);
    });
    task.ContinueWith((t) =>
    {
        Dispatcher.Invoke(() =>
        {
            Thumbnails.Add(img);
        });
    });

    UploadProgress = (int)Math.Round((double)(100 * b / files.Count()));
    b++;

1 个答案:

答案 0 :(得分:1)

您可能需要考虑使用async await运算符来使用Task对象的最新方法。

http://blog.stephencleary.com/2012/02/async-and-await.html

您实际上正在向UI发送代码中发生的任何进展。从技术上讲,我认为它仍在同步运行。 尝试使用continuewith进行如下调度:

var task = Task.Run(() =>
        {
            //simulate long operation
            Thread.Sleep(3000);
        });
        task.ContinueWith((t) =>
        {
            Dispatcher.Invoke(() =>
            {
                //do all UI operations here
            });
        });

我相信当您使用IProgress对象而不是使用调度程序更新UI时,您还可以保存大量代码。