While creating some pictures in another program I wanted to see the updated version of those pictures whenever they change on disk (in a folder).
Should be an easy task, right? System.IO.FileSystemWatcher
and then call the target Image.Dispatcher
and pass it a lambda which sets the new BitmapImage
. Only, it does not work as expected.
Snippet of code first:
private void Watcher_Changed(object sender, System.IO.FileSystemEventArgs e)
{
revCount++;
System.Diagnostics.Trace.WriteLine(e.ChangeType.ToString());
Action updateLabel = () => label.Content = e.FullPath;
label.Dispatcher.Invoke(updateLabel);
Action updateImage =
() =>
{
BitmapImage img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnLoad;
img.UriSource = new Uri(e.FullPath);
img.EndInit();
image.Source = img.Clone();
image.InvalidateVisual();
};
imgUpdateFilter.Event(updateImage);
// image.Dispatcher.Invoke(updateImage);
Action updateRevCount = () => revision.Content = revCount.ToString();
revision.Dispatcher.Invoke(updateRevCount);
}
Here is what happens:
- I start the application and then update an image in the target folder. The application shows the image (EXPECTED).
- I do it a second time (new version of image). And it does not update. (ERROR)
- I change another .png file in the folder and it displays it. (EXPECTED)
- I do it a third time (next new version of image). And it shows... the first version and not the last one. (ERROR)
This leads me to conclude that there is something fishy going on with clever caching, probably based on the imageUri
passed to the Image source.
Only I found no way to turn it off.
In the snippet above, you see the file system watcher event callback on changed. It gets called (3 times!) each time I update my image.
Also possibly of interest is, that if I play with the img.CacheOption = BitmapCacheOption.OnLoad;
line and set it for example to Default
, then the file is locked, which of course is not desired as I want to render new versions of the file... This is another hint, that something funny is going on.
As you can see in the snippet, I tried to img.Clone()
, hoping this would break the sneaky behavior and get me what I want but ... no... does not change a thing.
So, who can tell me what to do to get that Image
wpf thing to do what I want?