使用不同的Thread更改Listbox ItemsSource

时间:2016-09-06 17:01:28

标签: c# wpf multithreading listbox thread-safety

我想在没有UI冻结的情况下更改ListBox ItemsSource。对于这个挑战,我编写了你在下面看到的代码;

当用户点击按钮

output =
  new FileOutputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filen[filen.length-1]));

异步方法

   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://siebel.com/WebService">
   <soapenv:Header>
    <UsernameToken xmlns="http://siebel.com/webservices">XXXXXXX</UsernameToken>
    <PasswordText xmlns="http://siebel.com/webservices"></PasswordText>
    <SessionType xmlns="http://siebel.com/webservices">Stateless</SessionType>   
 </soapenv:Header>
 <soapenv:Body>
  <web:QuerySR_Input>
     <web:SRNum>450545194</web:SRNum>
  </web:QuerySR_Input>
     </soapenv:Body>
   </soapenv:Envelope> 

更改ItemsSource

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

在最后一个方法中,如果我直接更改ListBox的ItemSource,程序不会中断,但是当程序传递给方法的封闭大括号时,会分解并抛出必须在同一个线程上创建DependencySource DependencyObject 异常。

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

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

但是,如果我改变这样的代码,那就完美了,并将项目添加到我的列表框中。

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

我真的不理解我的失踪。为什么我可以添加一些字符串,但我无法添加到我的FileListItem类。我错过了什么?我已经尝试了很多不同的代码,但它总是打破封闭的花括号而不是在配置线上。

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

1 个答案:

答案 0 :(得分:0)

您的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;

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

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