Microsoft Developer Network > Forenhomepage > Windows Presentation Foundation (WPF) > A way to use BitmapMetadata outside the main thread?

Beantwortet A way to use BitmapMetadata outside the main thread?

  • Freitag, 16. Mai 2008 14:15
     
     
    Hi,

    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:13
    Moderator
     
     Beantwortet

    You can set thread apartment to STA and IsBackground property to false to do this.

     

    Code Snippet

    Thread.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:41
     
     
    Hey 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:13
    Moderator
     
     Beantwortet

    You can set thread apartment to STA and IsBackground property to false to do this.

     

    Code Snippet

    Thread.SetApartmentState(ApartmentState.STA);

    Thread.IsBackground = false;

     

     

    Best Regards,

    Wei Zhou

  • Montag, 19. Mai 2008 14:11
     
     
    Thanks Wei Zhou!

    That did the job!