J'ai deux classes ViewModel: PersonViewModel et PersonSearchListViewModel. L'un des champs que PersonViewModel implémente est une image de profil qui est téléchargée via WCF (mise en cache localement dans un stockage isolé). PersonSearchListViewModel est une classe de conteneur qui contient une liste de personnes. Puisque le chargement des images est relativement lourd, PersonSearchListViewModel ne charge que les images de la page courante, suivante et précédente (les résultats sont paginés sur l'interface utilisateur) ... pour améliorer la charge des images, je charge les images sur un autre thread. Toutefois, l'approche multi-thread entraîne des problèmes d'accès inter-thread.Problème d'accès à un thread non valide
PersonViewModel:
public void RetrieveProfileImage()
{
Image profileImage = MemorialDataModel.GetImagePerPerson(Person);
if (profileImage != null)
{
MemorialDataModel.ImageManager imgManager = new MemorialDataModel.ImageManager();
imgManager.GetBitmap(profileImage, LoadProfileBitmap);
}
}
private void LoadProfileBitmap(BitmapImage bi)
{
ProfileImage = bi;
// update
IsProfileImageLoaded = true;
}
private BitmapImage profileImage;
public BitmapImage ProfileImage
{
get
{
return profileImage;
}
set
{
profileImage = value;
RaisePropertyChanged(new System.ComponentModel.PropertyChangedEventArgs("ProfileImage"));
}
}
PersonSearchListViewModel:
private void LoadImages()
{
// load new images
Thread loadImagesThread = new Thread(new ThreadStart(LoadImagesProcess));
loadImagesThread.Start();
//LoadImagesProcess(); If executed on the same thread everything works fine
}
private void LoadImagesProcess()
{
int skipRecords = (PageIndex * PageSize);
int returnRecords;
if (skipRecords != 0)
{
returnRecords = 3 * PageSize; // page before, cur page and next page
}
else
{
returnRecords = 2 * PageSize; // cur page and next page
}
var persons = this.persons.Skip(skipRecords).Take(returnRecords);
// load images
foreach (PersonViewModel pvm in persons)
{
if (!pvm.IsProfileImageLoaded)
{
pvm.RetrieveProfileImage();
}
}
}
Comment traiter les données que vous en classe ViewModel de manière multi-thread? Je sais que vous devez utiliser Dispatcher sur l'interface utilisateur pour mettre à jour. Comment mettez-vous à jour ViewModel qui est lié à l'interface utilisateur?
** EDIT **
Il y a aussi une erreur plus étrange qui se passe. Dans le code ci-dessous:
public void GetBitmap(int imageID, Action<BitmapImage> callback)
{
// Get from server
bitmapCallback = callback;
memorialFileServiceClient.GetImageCompleted += new EventHandler<GetImageCompletedEventArgs>(OnGetBitmapHandler);
memorialFileServiceClient.GetImageAsync(imageID);
}
public void OnGetBitmapHandler(object sender, GetImageCompletedEventArgs imageArgs)
{
if (!imageArgs.Cancelled)
{
// I get cross-thread error right here
System.Windows.Media.Imaging.BitmapImage bi = new BitmapImage();
ConvertToBitmapFromBuffer(bi, imageArgs.Result.Image);
// call call back
bitmapCallback.Invoke(bi);
}
}
Je reçois une erreur cross-thread lors de la tentative de création d'un nouvel objet BitmapImage dans le thread d'arrière-plan. Pourquoi ne puis-je pas créer un nouvel objet BitmapImage sur un thread d'arrière-plan?
Grand, qui est exactement ce que je cherchais. Je suis allé avec byte [] comme un moyen de stockage. – Ender
cela m'a également aidé quand j'ai dû déclencher un événement PropertyChanged pour plusieurs propriétés après avoir été défini. –
Je ne me suis pas rendu compte qu'un BitmapImage devait être fait sur le fil de l'interface utilisateur. J'aurais vraiment dû y penser car un DependencyProperty serait un problème autrement. :: facepalm :: – Paul