A way to use BitmapMetadata outside the main thread?
-
Freitag, 16. Mai 2008 14:15Hi,
I'm developing a multi-threaded C# application and have run into problems while using the BitmapMetadata component outside the main (UI) thread and UI class. My app throws 'System.Runtime.InteropServices.COMException' occurred in PresentationCore.dll and when I try to debug it and put a Watch on the BitmapMetadata object, it takes forever to access its properties and when it does so, most of them are marked with "Function evaluation disabled because a previous function evaluation timed out."
In view of the articles:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1646928&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1653994&SiteID=1
I figured that my problems are due to the fact that WPF components are not to be used outside the STAThread. My question now is whether I am right (:-) and if there is some kind of workaround to the BitmapMetadata object working outside the main thread? Unfortunately, I'm not only dealing with a different thread, but also the BitmapMetadata object is to be used by a class different from the UI class.
Any suggestions?
Thanks in advance!!!
Antworten
-
Montag, 19. Mai 2008 06:13Moderator
You can set thread apartment to STA and IsBackground property to false to do this.
Code SnippetThread.SetApartmentState(ApartmentState.STA);
Thread.IsBackground = false;
Best Regards,
Wei Zhou
Alle Antworten
-
Freitag, 16. Mai 2008 14:20
Does freezing the BitmapMetadata before your non-ui thread accesses it help?
-Jer
-
Freitag, 16. Mai 2008 14:41Hey Jer, thanks for your response!I'm sorry! I should have posted some code to make my issue clearer. Below is an excerpt. Basically it's a modfication of an example I found on the web that I use for testing.
Code Snippet
namespace IPTC_Test
{
class Program
{
[STAThread]
static void Main()
{
Thread t = new Thread(startApp);
t.Start();
Application.Run(new Form1());
}
static void startApp()
{
Program p = new Program();
p.writeMetadataDotNet();
}
private void writeMetadataDotNet()
{
string originalPath = "test.jpg";
string outputPath = "test2.jpg";
BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;
uint paddingAmount = 2048;
using (Stream originalFile = File.Open(originalPath, FileMode.Open, FileAccess.Read))
{
BitmapDecoder original = BitmapDecoder.Create(originalFile, createOptions, BitmapCacheOption.None);
if (!original.CodecInfo.FileExtensions.Contains("jpg"))
{
Console.WriteLine("The file you passed in is not a JPEG.");
return;
}
JpegBitmapEncoder output = new JpegBitmapEncoder();
if (original.Frames[0] != null && original.Frames[0].Metadata != null)
{
try
{
BitmapMetadata metadata = new BitmapMetadata("jpg");
// If I set a breakpoint after here and try to access/debug the metadata object, it fails. If I let it run through, the "output.Save" function below throws the exception mentioned in the first post
metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount);
metadata.SetQuery("/app1/ifd/exif/PaddingSchema:Padding", paddingAmount);
metadata.SetQuery("/xmp/PaddingSchema:Padding", paddingAmount);
string[] strArr = new string[2];
strArr[0] = "one";
strArr[1] = "two";
metadata.SetQuery("/app13/irb/8bimiptc/iptc/keywords", strArr);
output.Frames.Add(BitmapFrame.Create(original.Frames[0], original.Frames[0].Thumbnail, metadata, original.Frames[0].ColorContexts));
using (Stream outputFile = new FileStream("test2.jpg", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
{
output.Save(outputFile);
}
}
catch (Exception e)
{
int einienv = 3883;
}
}
}
}
} -
Montag, 19. Mai 2008 06:13Moderator
You can set thread apartment to STA and IsBackground property to false to do this.
Code SnippetThread.SetApartmentState(ApartmentState.STA);
Thread.IsBackground = false;
Best Regards,
Wei Zhou
-
Montag, 19. Mai 2008 14:11Thanks Wei Zhou!
That did the job!

