B
Buck3
Guest
I have been looking posts but do not see how to do this. This is a C#/WPF application.
I am wondering is there a way to create a BitmapSource on a second thread and successfully return and use it in the main UI thread? If not, would you mind explaining the theory why not? It seems like it is created on the heap which it seems like we should be able to share between threads. I understand if it is a stack based variable which would potentially be different since different threads have different stacks.
My code is as follows:
Code that starts the new thread is here and which ultimately creates the BitmapSource in OpenImageFromFile. The purpose of the new thread is to allow other UI display/progress to occur while the file is loading.
// Start a separate task/thread that will join up with the main UI thread below passing it the return value
var result = Task<BitmapSource>.Factory.StartNew(() => ImageHelper.OpenImageFromFile(fileList[0]));
...// Other work such as progress indication on the UI
// Wait for the task opening the file to complete
result.Wait();
// Get the bitmapsource for use
BitmapSource bitmapSource = result.Result;
Sometime later, the code below is called and causes the exception at the encoder.Frames.Add line below. The exception has the description "The calling thread cannot..." as stated above. The code below is part of saving an image file based on the BitmapSource.
...
// Create encoder and check that was created successfully
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
if (encoder == null)
{
return false;
}
// Load encoder
encoder.Compression = TiffCompressOption.Zip;
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
// Save stream
encoder.Save(stream);
...
Note: the detail for the OpenImageFromFile call is below which is used when creating a new thread (and which creates the BitmapSource):
/// <summary>
/// Opens an image from file.
/// </summary>
/// <param name="filename The filename.</param>
/// <returns>
/// Returns bitmapSource with file contents and returns null if unsuccessful.
/// </returns>
public static BitmapSource OpenImageFromFile(string filename)
{
BitmapSource bitmapSource = null;
try
{
// Open a Stream and decode a TIFF image
Stream imageStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// If result is null then return back indicating unsuccessful.
if (imageStreamSource == null)
{
return null;
}
// Create decoder from image stream
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
// If result is null then return back indicating unsuccessful.
if (decoder == null)
{
return null;
}
// Return the final result
bitmapSource = decoder.Frames[0];
}
catch (Exception ex)
{
Debug.WriteLine("Exception {0}", ex.ToString());
throw;
}
return bitmapSource;
}
Any help is much appreciated.
Buck
Continue reading...
I am wondering is there a way to create a BitmapSource on a second thread and successfully return and use it in the main UI thread? If not, would you mind explaining the theory why not? It seems like it is created on the heap which it seems like we should be able to share between threads. I understand if it is a stack based variable which would potentially be different since different threads have different stacks.
My code is as follows:
Code that starts the new thread is here and which ultimately creates the BitmapSource in OpenImageFromFile. The purpose of the new thread is to allow other UI display/progress to occur while the file is loading.
// Start a separate task/thread that will join up with the main UI thread below passing it the return value
var result = Task<BitmapSource>.Factory.StartNew(() => ImageHelper.OpenImageFromFile(fileList[0]));
...// Other work such as progress indication on the UI
// Wait for the task opening the file to complete
result.Wait();
// Get the bitmapsource for use
BitmapSource bitmapSource = result.Result;
Sometime later, the code below is called and causes the exception at the encoder.Frames.Add line below. The exception has the description "The calling thread cannot..." as stated above. The code below is part of saving an image file based on the BitmapSource.
...
// Create encoder and check that was created successfully
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
if (encoder == null)
{
return false;
}
// Load encoder
encoder.Compression = TiffCompressOption.Zip;
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
// Save stream
encoder.Save(stream);
...
Note: the detail for the OpenImageFromFile call is below which is used when creating a new thread (and which creates the BitmapSource):
/// <summary>
/// Opens an image from file.
/// </summary>
/// <param name="filename The filename.</param>
/// <returns>
/// Returns bitmapSource with file contents and returns null if unsuccessful.
/// </returns>
public static BitmapSource OpenImageFromFile(string filename)
{
BitmapSource bitmapSource = null;
try
{
// Open a Stream and decode a TIFF image
Stream imageStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// If result is null then return back indicating unsuccessful.
if (imageStreamSource == null)
{
return null;
}
// Create decoder from image stream
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
// If result is null then return back indicating unsuccessful.
if (decoder == null)
{
return null;
}
// Return the final result
bitmapSource = decoder.Frames[0];
}
catch (Exception ex)
{
Debug.WriteLine("Exception {0}", ex.ToString());
throw;
}
return bitmapSource;
}
Any help is much appreciated.
Buck
Continue reading...