Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用WPF在线程中加载图像_C#_Wpf_Image_List_Multithreading - Fatal编程技术网

C# 使用WPF在线程中加载图像

C# 使用WPF在线程中加载图像,c#,wpf,image,list,multithreading,C#,Wpf,Image,List,Multithreading,我正在尝试制作一个列表框来显示来自互联网的图片。通过将itemsource绑定到包含图像URL和一些其他属性title、desc等的模型来提供这些项 不幸的是,加载列表的速度非常慢,因为WPF试图在显示列表之前从web下载所有图片,这会使应用程序冻结15到25秒 我已经读到我应该在另一个线程加载图片,但我不知道我应该在哪里做,如何做?直接在模型中加载所有图片是否更好?只为此创建一个线程池,但问题是它实际上不是模型/模型视图的一部分,还是创建一个背景线程,在列表有数据时直接更新列表更好 谢谢 一个

我正在尝试制作一个列表框来显示来自互联网的图片。通过将itemsource绑定到包含图像URL和一些其他属性title、desc等的模型来提供这些项

不幸的是,加载列表的速度非常慢,因为WPF试图在显示列表之前从web下载所有图片,这会使应用程序冻结15到25秒

我已经读到我应该在另一个线程加载图片,但我不知道我应该在哪里做,如何做?直接在模型中加载所有图片是否更好?只为此创建一个线程池,但问题是它实际上不是模型/模型视图的一部分,还是创建一个背景线程,在列表有数据时直接更新列表更好


谢谢

一个非常简单的方法是在视图模型中使用System.ComponentModel.BackgroundWorker。下面是一个简单的例子:

using (BackgroundWorker bg = new BackgroundWorker())
{
    bg.DoWork += (sender, args) => FetchImages(viewModelObjectsNeedingImages);
    bg.RunWorkerAsync();
}
BackgroundWorker还可以非常方便地取消后台任务


你可能还想看看

一个非常简单的方法是在视图模型中使用System.ComponentModel.BackgroundWorker。下面是一个简单的例子:

using (BackgroundWorker bg = new BackgroundWorker())
{
    bg.DoWork += (sender, args) => FetchImages(viewModelObjectsNeedingImages);
    bg.RunWorkerAsync();
}
BackgroundWorker还可以非常方便地取消后台任务

你可能还想看看

您可以使用将数据源绑定到列表框,并且仍然可以将数据加载到另一个线程中

有关如何编写这样一个线程的示例,请查看文档

此外,您可能需要考虑对图像的懒惰加载,即只加载可见的和在任何时候多的图像。通过这种方式,您可以获得两个好处:在获取线程中的图像时不必阻塞UI,并且您可以重用您的集合,一次只保存几个图像,防止在计划显示(比如)几千个图像时,一次用大量图像填充内存。查看有关如何实现这种虚拟化的详细信息。

您可以使用它将数据源绑定到列表框,并且仍然可以在另一个线程中加载数据

有关如何编写这样一个线程的示例,请查看文档


此外,您可能需要考虑对图像的懒惰加载,即只加载可见的和在任何时候多的图像。通过这种方式,您可以获得两个好处:在获取线程中的图像时不必阻塞UI,并且您可以重用您的集合,一次只保存几个图像,防止在计划显示(比如)几千个图像时,一次用大量图像填充内存。查看有关如何实现此类虚拟化的详细信息。

简单的方法是只需设置Binding.IsAsync属性,如下所示:

<Image ImageSource="{Binding propertyThatComputesImageSource, IsAsync=true}" />
如果模型的属性是DependencyProperty,则可能需要使用Dispatcher.Invoke或两个来扩展,因为它们不能从单独的线程访问


这项技术可以扩展到产生固定数量的工作人员来加载图像,并中断它们之间的工作,以便进行多个图像下载,但同时下载的数量是有限的,因此您不会有数百个线程。

简单的方法是只需设置Binding.IsAsync属性,如下所示:

<Image ImageSource="{Binding propertyThatComputesImageSource, IsAsync=true}" />
如果模型的属性是DependencyProperty,则可能需要使用Dispatcher.Invoke或两个来扩展,因为它们不能从单独的线程访问

这项技术可以扩展到产生固定数量的工作人员来加载图像,并将它们之间的工作分解,这样就可以进行多个图像下载,但同时下载的数量是有限的,这样您就不会有数百个线程。

感谢大家

所有的解决方案都应该有效:在我的例子中,在ListBoxItem的图像上使用IsAsync就足够了,最多有50个项目。事实上,它并不是从网络上检索图像,这花费了太多的时间

不幸的是我的问题出在别的地方。。。这与.NET 3.5中的代理检测错误有关,该错误导致应用程序加载非常缓慢:

如果应用程序文件夹中没有包含以下代码的\u application\u name.exe.config文件-.NET可能需要大量时间来检测代理,该代理会在应用程序首次访问网络时冻结应用程序:

<configuration>   
  <system.net>
    <defaultProxy enabled="false"/>   
  </system.net> 
</configuration>
谢谢大家

所有的解决方案都应该有效:在我的例子中,在ListBoxItem的图像上使用IsAsync就足够了,最多有50个项目。事实上,它并不是从网络上检索图像,这花费了太多的时间

不幸的是我的问题出在别的地方。。。这与.NET 3.5中的代理检测错误有关,该错误导致应用程序加载非常缓慢:

如果应用程序文件夹中没有任何包含t的\u应用程序\u name.exe.config文件 以下代码-.NET可能需要花费大量时间来检测代理,该代理在应用程序首次访问网络时会冻结应用程序:

<configuration>   
  <system.net>
    <defaultProxy enabled="false"/>   
  </system.net> 
</configuration>

只要确保SynchronizationContext.Current在BackgroundWorker启动时是有意义的。应该是WPF上下文,但要记住。请确保SynchronizationContext.Current在BackgroundWorker启动时有意义。应该是WPF上下文,但只是需要记住的东西。