Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I'm new to WPF and vb.net programming and now I'm learning how backgroundworker works.

I'm building simple app to load image (to keep it simple, from a fixed path, like, "\\Server-01\d\ScanToLao31414.jpg") when user click a "Load Button". While Loading, the "Loading..." text appears.

The Background worker should do loading image in background thread. When it ready, it should return Bitmapimage to display on UI thread. The "Loading..." text shoul now gone.

The whole step should not freeze user interface.

The Error: Image1.Source = ThisIsImageReady ---> The calling thread cannot access this object because a different thread owns it.

Question: Are there anything to do with dispatcher on UI thread? I thought backgroundworker take care of that already?

(Part of )XAML:
XML
<Window.Resources>
    <cm:BackgroundWorker
        x:Key="backgroundWorker"
        WorkerReportsProgress="True"
        WorkerSupportsCancellation="True"
        DoWork="backgroundWorker_DoWork"
        RunWorkerCompleted="backgroundWorker_RunWorkerCompleted">
    </cm:BackgroundWorker>
</Window.Resources>


The Code:

Imports System.ComponentModel

Class Window1
    Private backgroundWorker As BackgroundWorker
    Public Sub New()
        InitializeComponent()
        backgroundWorker = CType(Me.FindResource("backgroundWorker"), BackgroundWorker)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Button1.IsEnabled = False
        Button2.IsEnabled = True
        TextBlock1.Visibility = Windows.Visibility.Visible
        backgroundWorker.RunWorkerAsync(New InputString("\\Server-01\d\ScanToLao31414.jpg"))
    End Sub
    Private Sub backgroundWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        Dim input As InputString = CType(e.Argument, InputString)
        Dim ThisIsImage As BitmapImage = Loadimage.LoadNow(input.inString, backgroundWorker)
        e.Result = ThisIsImage
    End Sub
    Private Sub backgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        If Not e.Error Is Nothing Then
            MessageBox.Show(e.Error.Message, "An Error Occurred")
        Else
            Dim ThisIsImageReady As BitmapImage = CType(e.Result, BitmapImage)
            Image1.BeginInit()
            Image1.Source = ThisIsImageReady
            Image1.EndInit()
        End If
        Button1.IsEnabled = True
        Button2.IsEnabled = False
        TextBlock1.Visibility = Windows.Visibility.Hidden
    End Sub
End Class

Public Class Loadimage
    Public Shared Function LoadNow(ByVal loadstring As String, ByVal backgrounworker As BackgroundWorker) As BitmapImage
        Dim bmp As New BitmapImage(New Uri(loadstring, UriKind.RelativeOrAbsolute))
        bmp.CacheOption = BitmapCacheOption.OnLoad
        LoadNow = bmp
        Return LoadNow
    End Function
End Class

Public Class InputString
    Private _string As String
    Public Property inString() As String
        Get
            Return _string
        End Get
        Set(ByVal value As String)
            _string = value
        End Set
    End Property
    Public Sub New(ByVal newInputString As String)
        Me.inString = newInputString
    End Sub
End Class
Posted
Updated 11-Feb-10 20:37pm
v2

1 solution

The reason you've got this exception is that the "BitmapImage" class is derived from "DispatcherObject", which means that only one thread can access it at the same time, any other attempt will throw that exception. But as it is derived from class "Freezable" also, you can freeze the object, which means that no changes can be made further to that object, and so, it can be used in other threads. As you crated your object in the background thread, it's Dispatcher is assigned to the background thread initially, and after modification of the object, I would suggest you to freeze it after initialization. I am sure this will fix your problem.

VB
Dim ThisIsImage As BitmapImage = Loadimage.LoadNow(input.inString, backgroundWorker)
ThisIsImage.Freeze()
e.Result = ThisIsImage
 
Share this answer
 
Comments
Tarun.K.S 6-Jan-11 11:40am    
Good answer! It worked perfectly!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900