所以我正在构建一个 WPF 控件,它需要从磁盘加载(和显示)400 到 600 个图像(每个图像的大小约为 200Kb。)。接下来是控件的代码隐藏。
private List<BitmapImage> pages = new List<BitmapImage>();
private BackgroundWorker worker;
public PagesListBox()
{
InitializeComponent();
worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = false;
worker.WorkerReportsProgress = false;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
List<BitmapImage> pagesList = new List<BitmapImage>();
var files = DirectoryServices.GetFiles(Properties.Settings.Default.PagesScanDirectory, new string[] { "*.tiff", "*.jpg", "*.png", "*.bmp" });
foreach (var file in files)
{
Uri uri = new Uri(file);
pagesList.Add(new BitmapImage(uri));
}
e.Result = pagesList;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Pages.ItemsSource = (List<BitmapImage>)e.Result;
}
internal void LoadPages()
{
worker.RunWorkerAsync();
}
internal List<BitmapImage> AttachPages()
{
List<BitmapImage> attachedPages = new List<BitmapImage>();
foreach (BitmapImage eachItem in Pages.SelectedItems)
{
attachedPages.Add(eachItem);
pages.Remove(eachItem);
}
Pages.ItemsSource = null;
Pages.ItemsSource = pages;
return attachedPages;
}
我尝试将页面列表分配给 View (我不能使用后台工作程序),但它失败了。
是否有任何其他异步加载图像的方法(可能更新 UI)或我正在尝试的后台 worker 的这种方法很好。而且,如果没问题,我该如何解决异常(在完成的事件中):
Must create DependencySource on same Thread as the DependencyObject.
谢谢
最佳答案
为了简化您的代码,使用 ObservableCollection<> 而不是 List<> 并且只分配一次 ItemsSource 属性。
线程错误是因为您正在创建位图并将其添加到后台工作线程而不是主 UI 线程上的列表。要解决此问题,请使用 DispatcherHelper(取自 Laurent Bugnion 的 MVVMLight Framwwork)。
如果您要进行大量 WPF 开发,我建议您将 MVVM 视为一种应用程序设计方法,而不是仅仅按照“Winforms 方式”进行操作,尽管这是一种完全不同的思维方式。
...
DispatcherHelper.Initialise()
...
private ObservableCollection<BitmapImage> _Pages = new ObservableCollection<BitmapImage>();
public PagesListBox()
{
InitializeComponent();
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = false;
worker.WorkerReportsProgress = false;
worker.DoWork += worker_DoWork;
this.ItemSource = _Pages;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
var files = DirectoryServices.GetFiles(Properties.Settings.Default.PagesScanDirectory, new string[] { "*.tiff", "*.jpg", "*.png", "*.bmp" });
foreach (var file in files)
{
DispatcherHelper.CheckBeginInvokeOnUI(()=>
{
Uri uri = new Uri(file);
_Pages.Add(new BitmapImage(uri));
});
}
}
public static class DispatcherHelper
{
public static Dispatcher UIDispatcher { get; private set; }
public static void CheckBeginInvokeOnUI(Action action)
{
if (UIDispatcher.CheckAccess())
action();
else
UIDispatcher.BeginInvoke(action);
}
public static void Initialize()
{
if (UIDispatcher != null)
return;
UIDispatcher = Dispatcher.CurrentDispatcher;
}
}
关于c# - 异步图像加载到列表框中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10134259/