I have two ViewModel classes : PersonViewModel and PersonSearchListViewModel. One of the fields PersonViewModel implements is a profile image that is downloaded via WCF(cached locally in isolated storage). The PersonSearchListViewModel is a container class that holds a list of Persons. Since loading images is relatively heavy, PersonSearchListViewModel loads only images for the current, next and previous page (results are paged on UI)...to further improve the load of images I put the load of images on another thread. However multi-threading approach causes cross-thread access issues.
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();
}
}
}
How do you process data in ViewModel class in multi-threaded manner ? I know you have to use dispatcher on UI to update. How do you update ViewModel that is bound to UI ?
** EDIT **
There is also one more weird error happening. In the code below :
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);
}
}
I get a cross-thread error when trying to create a new BitmapImage object in background thread. Why can't I create a new BitmapImage object on a background thread ?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…