2012-06-12 2 views
4

Я работаю над C# WPF-приложением, которое загружает много изображений и отображает его как миниатюры. Я бы хотел сделать это многопоточным способом. Поэтому я попытался реализовать BackgroundWorker.Загрузка изображений asynchronous в C#

Код DoWork в BackgroundWorker (в):

string[] files = e.Argument as string[]; 
foreach (string file in files) 
{ 
    ImageModel image = new ImageModel(); 
    image.FilePath = file; 
    _importWorker.ReportProgress(1, image); 
    _imageCollectionVM.Images.Add(image); // also tried this one in ReportProgress() 
} 

В моем XAML коде привязки к свойству BitmapImage из ImageModel. (AsyncState = True не помогает.) Здесь я получаю эту ошибку: «DependencySource» и «DependencyObject» должны быть в одном потоке.

<Image Source="{Binding BitmapImage}" /> 

Если я прокомментирую это, изображение, кажется, импортировано, но я не могу получить к нему доступ, например. выбрав его в ListView. В своем SelectionChanged он говорит тогда, что этот объект обладает другим потоком.

Как решить эти проблемы? Заранее спасибо!

ответ

1

ПРЕДПОСЫЛКИ работник хорошо имо для больших задач, но если это что-то простое, как то, что вы е делать я предпочел бы, чтобы это сделать, как этот

начала со списком Image

List<Image> Images =new List<Image>(); 

затем запустить этот

Task.Factory.StartNew(() => 
{ 
    string[] files = e.Argument as string[]; 
    foreach (string file in files) 
    { 
     ImageModel image = new ImageModel(); 
     image.FilePath = file; 
     // _importWorker.ReportProgress(1, image); 

     this.BeginInvoke(new Action(() => 
     { 
      Images.Add(image); 
     })); 
    } 
}); 

Нет гарантии, у меня есть нужное количество скобок в этом коде.

+0

Я полагаю, что мне нужно использовать метод 'BeginInvoke'' this.Dispatcher', правильно? На самом деле, у меня уже есть ObservableCollection, к которому я привязываю источник элементов ListView (обновленный оригинальный пост). Но если я делаю 'imageCollectionVM.Images.Add (изображение);' внутри Action, я получаю сообщение об ошибке «DependencySource и DependencyObject должно быть в одном потоке». – Sentropie

+0

Если вы пытаетесь использовать ObservableCollection, см. Последнюю ссылку, которую я опубликовал в своем ответе, у нее есть BindingList <>, который может быть обновлен из фонового потока. –

2

Вы должны перенести обновление в графический интерфейс в основной поток. В основном вы можете выполнять многопоточную загрузку изображений с диска, но фактическое обновление GUI должно выполняться однопоточно.

Существует много способов сделать это, и многие вопросы по stackoverflow адресуют его. Вот несколько, чтобы вы начали

Update UI from background Thread

Update BindingList<> from a background Thread?

Is it evil to update a pictureBox from a background C# thread?

Как использовать BindingList для этого

How do you correctly update a databound datagridview from a background thread

0

В подобной ситуации я сделал следующее:

  • создать класс ImageProvider, который фактически выполняет загрузку изображений работы
  • пусть ViewModel из Bind изображений в ImageSource в моем ItemViewModel
  • пусть это ImageSource поленитесь

    // // псевдокод здесь

    Lazy lazy = new Lazy (imageProvider.LoadImage (this.imagePath))

    // в ImageViewModel ...

    imageSource {get {return lazy.Value; }}

+0

Будет ли класс ImageProvider использовать многопоточность или в том, как обеспечивается, что GUI isn Не замораживать? – Sentropie

+0

в моем случае изображениепровайдер не работает в потоке пользовательского интерфейса. возможно, вот некоторая работа, которая должна быть сделана для этого примера. –

+0

@Сентропия: два шага, чтобы сделать это, чтобы развязать его правильно, я верю. –

Смежные вопросы