Skip to main content

Microsoft Silverlight

Answered Question cross thread accessRSS Feed

(0)

mexican
mexican

Member

Member

164 points

713 Posts

cross thread access

 Hi,

I am getting a cross thread access error, when loading an image in a background thread

How do i fix this?

 

Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)


     Dim bw As BackgroundWorker = New BackgroundWorker
     
 AddHandler bw.DoWork, AddressOf bw_DoWork
      ...
        For i = 1 To 10
            System.Threading.Thread.Sleep(500)
            bw.ReportProgress(i * 10)
            a.X = i
            a.Y = i
            e.Result = "l"
        Next

        img = New Image
        _x = 100
        _y = 300
        url = New Uri("images/circle.png", UriKind.Relative)
        uu = New BitmapImage(url)
        uu.UriSource = url
        img.Source = uu
        Canvas.SetLeft(img, _x)
        Canvas.SetTop(img, _y)
        Canvas.SetZIndex(img, 10)
        canvas1.Children.Add(img)
        AddHandler uu.ImageOpened, AddressOf uu_downloadComplete

    End Sub
 

mexican
mexican

Member

Member

164 points

713 Posts

Re: cross thread access

this works but I am not sure if there can be problems with this method

    Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)

     
        For i = 1 To 10
            System.Threading.Thread.Sleep(500)
            bw.ReportProgress(i * 10)
            a.X = i
            a.Y = i
            e.Result = "l"
        Next
     
    End Sub
    
 

    Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
        img = New Image
        _x = 100
        _y = 300
        url = New Uri("images/circle.png", UriKind.Relative)
        uu = New BitmapImage(url)
        uu.UriSource = url
        img.Source = uu
        Canvas.SetLeft(img, _x)
        Canvas.SetTop(img, _y)
        Canvas.SetZIndex(img, 10)
        canvas1.Children.Add(img)
        AddHandler uu.ImageOpened, AddressOf uu_downloadComplete


        Me.tb1.Text = e.ProgressPercentage.ToString() & "%"

       
    End Sub
 

K2P2
K2P2

Participant

Participant

1028 points

337 Posts

Re: cross thread access

I don't know about that but here's another way to do it - maybe.  With little work:

(NOTE:  you cannot use i.Loaded event because all the loaded event tells you is that the "Silverlight Image control" has loaded which is not the same as the underlying bits that you are "downloading".)

...
Image I = new Image ();
i.Source = ...
I.ImageFailed += new EventHandler(I_ImageFailed);
I.ImageOpened += new EventHandler(I_ImageOpened);
...
void I_ImageOpened(object sender, RoutedEventArgs e)
{
   Add opened image to parent

   Image I = new Image ();
   i.Source = ...
   I.ImageFailed += new EventHandler(I_ImageFailed);
   I.ImageOpened += new EventHandler(I_ImageOpened);
}

void I_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
   Add an error "control" to the parent.

   Image I = new Image ();
   i.Source = ...
   I.ImageFailed += new EventHandler(I_ImageFailed);
   I.ImageOpened += new EventHandler(I_ImageOpened);
}
 

 

mexican
mexican

Member

Member

164 points

713 Posts

Re: cross thread access

I know how to do it that way but I am learning how to open a lot of images using a thread.

After this I need a bigger example but first how do i use the backgroundworker for a small example.

K2P2
K2P2

Participant

Participant

1028 points

337 Posts

Re: cross thread access

I don't envy you.

Here are some of the reasons why, as you probably have already thought about:

1)  If you are loading from "a" server there is no gaurantee how long an image can take to "arrive".  It can bounce around different routers for quite a while.

2)  In your "on completed" handler how do you know which image completed (I'm sure there's a way to tag them - somehow)?  Since you are starting a new load every X milliseconds what happens if ten images haven't completed yet?  On the client side, if they have a wireless connection, things can get pretty bogged down.  If they have a slow computer - even worse.

3)  AutoResetEvent's and Monitor's

 

mexican
mexican

Member

Member

164 points

713 Posts

Re: Re: cross thread access

ok we are getting a little of the thread topic as all i wish to know is how in vb.net to update UI controls (image) from the background worker.

In c# you use a delegate in doWork event but in vb.net you use?

msalsbery
msalsbery

Contributor

Contributor

2066 points

379 Posts

Re: Re: cross thread access

 

mexican:
how in vb.net to update UI controls (image) from the background worker.

 

You can use the Dispatcher class' BeginInvoke method to execute a delegate (asynchronously!) on the UI thread, just like in C#

Dispatcher.BeginInvoke Method

 
(Note:  In the case of image loading, it's already done asynchronously (on another thread), so using a worker thread is kind of redundant.)

 

Are you still trying to figure out when all the images are downloaded like your discussion on another forum thread?  If so, this method isn't going to solve the issue, because the images are still being downloaded asynchronously so you still won't know they are all downloaded until all the ImageOpened and/or ImageFailed events are raised.

 

Mark Salsbery
Microsoft MVP - Visual C++

ksleung
ksleung

Contributor

Contributor

5396 points

1,028 Posts

Answered Question

Re: cross thread access

The portion of your code starting from "img = New Image" needs to be executed in the main UI thread.  I don't know how this is done in VB, but in C# you'd do something like this:

Dispatcher.BeginInvoke(() => { ... });

where ... is the portion of the code starting from "img = New Image".

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities