用不同的线程改变列表框ItemsSource

本文关键字:列表 ItemsSource 改变 线程 | 更新日期: 2023-09-27 18:05:49

我想改变ListBox ItemsSource没有UI冻结。对于这个挑战,我编写了如下代码;

当用户单击按钮

Thread th = new Thread(DisplayFilesAsync);
th.Start(new object[] { FolderPath, fdv.FileType });

异步方法

private void DisplayFilesAsync(object param)
{
     object[] args = param as object[];
     string searchText = Convert.ToString(args[0]);
     FileType type = (FileType)args[1];
     IEnumerable<FileListItem> list = uDirectoryHelper.GetFileFromFolder(searchText, type);
     Dispatcher.BeginInvoke(new Action<IEnumerable<FileListItem>>(DisplayFiles), DispatcherPriority.Background, new object[] { list });
}

改变ItemsSource

private void DisplayFiles(IEnumerable<FileListItem> fileList)
{
     lstFiles.ItemsSource = fileList;
}

在最后一个方法中,如果我直接改变ListBox的ItemSource,程序不会中断,但是当程序传递到方法的右花括号时,它会中断并抛出必须在与DependencyObject异常相同的线程上创建DependencySource。

如果我改变了;它再次在右花括号上断开,而不是在ADD方法上并抛出相同的异常。

private void DisplayFiles(IEnumerable<FileListItem> fileList)
{
    foreach (FileListItem item in fileList)
    {
        lstFiles.Items.Add(item);
    }
}

但是如果我像那样修改代码,它就可以完美地工作,并将项目添加到我的列表框中。

foreach (FileListItem item in fileList)
{
    lstFiles.Items.Add("EXAMPLE");
}
我真的不明白我的思念。为什么我可以添加到一些字符串,但我不能添加到我的FileListItem类。我错过了什么?我试过很多不同的代码,但它总是在不超过赋值线的闭花括号上中断。

我真的需要帮忙。谢谢你的回答。祝你有美好的一天,美好的工作。

用不同的线程改变列表框ItemsSource

你的FileListItem类有一个ImageSource类型的属性

public ImageSource ItemImage { get; set; }

虽然你没有在你的问题中显示,你肯定会在你的GetFileFromFolder方法中为该属性分配一个值,例如

fileList.ItemImage = new BitmapImage(new Uri(...));

除非BitmapImage没有被冻结在后台线程中,否则UI线程无法访问它,因此你会得到那个异常。

确保在BitmapImage加载位图后调用Freeze()方法。请注意,在这种情况下,您不能进行异步位图加载(例如通过远程URI)。如果您的位图是从本地文件加载的,请执行如下操作:

var bitmap = new BitmapImage();
using (var stream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = stream;
    bitmap.EndInit();
    bitmap.Freeze();        
}
fileList.ItemImage = bitmap;

或者,代替BitmapImage,使用BitmapFrame.Create()方法,它已经返回一个冻结的BitmapFrame (ImageSource的另一个子类)。

using (var stream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
    fileList.ItemImage = BitmapFrame.Create(
        stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}