Skip to main content
Home Forums General Silverlight Getting Started cross thread access
7 replies. Latest Post by ksleung on November 7, 2009.
(0)
mexican
Member
164 points
713 Posts
11-06-2009 4:25 AM |
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
11-06-2009 5:52 AM |
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
Participant
1028 points
337 Posts
11-06-2009 6:11 PM |
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);}
11-06-2009 6:22 PM |
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.
11-06-2009 7:23 PM |
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
11-06-2009 11:25 PM |
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
Contributor
2066 points
379 Posts
11-07-2009 1:51 PM |
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.
ksleung
5396 points
1,028 Posts
11-07-2009 5:53 PM |
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".