Results 1 to 11 of 11

Thread: [RESOLVED] VB.NET 08, WPF, Threads sharing Objects

  1. #1

    Thread Starter
    New Member
    Join Date
    Feb 2010
    Posts
    11

    Resolved [RESOLVED] VB.NET 08, WPF, Threads sharing Objects

    Hi,

    I#ve got a prolem whith threads sharing Objects. The exception is "The calling thread cannot access the object because a different thread owns it".

    My plan is to have a background thread that loads an image. As soon as it's loaded, I want the UI-Thread the display it.

    Code:
    Imports System.Windows.Media.Imaging
    
    Public Class test
      Private m_Bitmap As BitmapImage
    
      Public ReadOnly Property Bitmap() As BitmapImage
        Get
          Return m_Bitmap
        End Get
      End Property
    
    
      Public Sub run()
    
        m_Bitmap = New BitmapImage(New Uri("C:\Users\shess\Pictures\unbenannt1.png"))
    
      End Sub
    End Class
    
    
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    
        Dim o As New test()
        Dim t As New System.Threading.Thread(AddressOf o.run)
    
        t.IsBackground = True
        t.Start()
        'o.run()   'THIS wors, bacause no second thread
    
        t.Join()
    
        Image1.Source = o.Bitmap 'THIS throws the error, because o.Bitmap was created in another thread
    
      End Sub

    Help is very much appreciated!
    SP

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: VB.NET 08, WPF, Threads sharing Objects

    I haven't really worked with WPF so this is a bit of a guess. I read the documentation for the BitmapImage class and it says that it exists mainly to extend the BitmapSource class for use in XAML. As you're not using it in XAML, maybe try creating a BitmapSource instead and see if the same problem occurs. If it does then I would say that your only option would be to create the object on the UI thread if you intend to display it in the UI.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    New Member
    Join Date
    Feb 2010
    Posts
    11

    Re: VB.NET 08, WPF, Threads sharing Objects

    Thanks for you reply jmcilhinney,

    as far as I'm aware BitmapSource is MustInherit hence I can't create an instance of it. Or didn't I understand you fully?

  4. #4
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: VB.NET 08, WPF, Threads sharing Objects

    You can definitely use a BitmapImage as I've used it in the past, like so:

    vb Code:
    1. Image1.Source =  New BitmapImage(New Uri("C:\something.jpg"))

    but I dont know how you would get around the fact that it will only let you use it on the thread that created it I'm afraid

    Oh and you are correct that you cant create an instance of BitmapSource as it is declared MustInherit
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  5. #5
    Hyperactive Member Pac_741's Avatar
    Join Date
    Jun 2007
    Location
    Mexico
    Posts
    298

    Re: VB.NET 08, WPF, Threads sharing Objects

    Why don't you use a different aproach and use a background worker, I've done it before using WPF.
    You could use the completed event from the Backgroundworker and pass the image to the UI thread.

    I'd like to get a response from you.
    C# and WPF developer
    My Website:
    http://singlebits.com/

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: VB.NET 08, WPF, Threads sharing Objects

    Quote Originally Posted by Pac_741 View Post
    Why don't you use a different aproach and use a background worker, I've done it before using WPF.
    You could use the completed event from the Backgroundworker and pass the image to the UI thread.

    I'd like to get a response from you.
    The problem here is not the passing of data from one thread to another. The problem here is that the object cannot be used on a thread other than the one on which it was created. Using a BackgroundWorker won't change that. The DoWork event handler and the RunWorkerCompleted event handler are executed on different threads, so if you create the BitmapImage in the DoWork event handler and then try to use it in the RunWorkerCompleted event handler then you will encounter the same issue. Unlike a System.Drawing.Bitmap, which you would use in WinForms, it seems a System.Windows.Media.Imaging.BitmapImage is inherently associated with the thread on which it's created, much as a control is.

    If the only option is to use a BitmapImage object then I'd say that the only option is to create it on the UI thread.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    New Member
    Join Date
    Feb 2010
    Posts
    11

    Re: VB.NET 08, WPF, Threads sharing Objects

    I tried the backgroundworker, but it's indeed the same error.

    Creating and Loading the BitmapImage on the UI Thread is impossible. (Big picture up to 55MB across the network). That's why I currenty load a Winform Bitmap and convert it before using to BitmapImage. Unfortunately this convertion needs some (too much) time and needs to be done by the UI Thread.

    Any better ideas?

  8. #8
    Hyperactive Member Pac_741's Avatar
    Join Date
    Jun 2007
    Location
    Mexico
    Posts
    298

    Re: VB.NET 08, WPF, Threads sharing Objects

    Why don't you use WebRequest and download the image to a stream, and convert that to a byte array and pass it through the Completed event from the backgroundworker using e.result = img_byte_array.
    Once you get the bytes in the completed event, try converting it to a bitmapimage.

    It sounds good to me, what do you think ?
    C# and WPF developer
    My Website:
    http://singlebits.com/

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: VB.NET 08, WPF, Threads sharing Objects

    I read something today about the fact that many WPF objects can't be used on a thread other than the thread on which they were created EXCEPT Freezable objects that have been frozen. I just had a look at the documentation for the BitmapImage class and it does indeed inherit Freezable. That would imply that you can create this BitmapImage object on a secondary thread, freeze it, then use it on the UI thread. Exactly what's involved in freezing an object I don't know, but I'm guessing that it's a single property or method involved. I'd say that you should be able to look that up yourself.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  10. #10
    Hyperactive Member Pac_741's Avatar
    Join Date
    Jun 2007
    Location
    Mexico
    Posts
    298

    Re: VB.NET 08, WPF, Threads sharing Objects

    jmcilhinney, I've tried your suggestion but got no result.

    I guess my approach is the best way to go on this scenario.
    I don't have enough time to try it out, but I'm sure you could
    do it by yourself.
    C# and WPF developer
    My Website:
    http://singlebits.com/

  11. #11

    Thread Starter
    New Member
    Join Date
    Feb 2010
    Posts
    11

    Re: VB.NET 08, WPF, Threads sharing Objects

    Great! .freeze works! Thanks to all who were involved!

    For other people finding this thread: acording to MSDN there is no way to unfreeze an object other then cloning it and using a copy..


    vb Code:
    1. Imports System.Windows.Media.Imaging
    2.  
    3.  
    4. Class Window1
    5.   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    6.  
    7.     Dim o As New test()
    8.     Dim t As New System.Threading.Thread(AddressOf o.run)
    9.  
    10.     t.IsBackground = True
    11.     t.Start()
    12.  
    13.     t.Join()
    14.  
    15.     Image1.Source = o.Bitmap 'THIS works now
    16.   End Sub
    17. End Class
    18.  
    19.  
    20.  
    21. Public Class test
    22.   Private m_Bitmap As BitmapImage
    23.  
    24.   Public ReadOnly Property Bitmap() As BitmapImage
    25.     Get
    26.       Return m_Bitmap
    27.     End Get
    28.   End Property
    29.  
    30.  
    31.   Public Sub run()
    32.  
    33.     m_Bitmap = New BitmapImage(New Uri("C:\Users\shess\Pictures\unbenannt1.png"))
    34.     m_Bitmap.Freeze() 'THIS is the nub of the matter that makes it accessable by other threads.
    35.  
    36.   End Sub
    37. End Class

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width