Silverlight 2 brings support for threading to the browser. You can either directly start new threads using System.Threading.Thread and System.Threading.ThreadPool, or you can use the higher-level (and recommended) System.ComponentModel.BackgroundWorker type. The latter encapsulates the concept of executing work in the background (using a thread from the thread-pool) and updating the UI based on progress and/or completion of that work, which means that you can safely update the UI from the related events.

A lesser-known type that we introduced in beta 1 is System.Windows.Threading.Dispatcher. This type lets you execute work on the UI thread - something that's useful when you directly want to update the UI from a background thread. Since Silverlight always has a single UI-thread, there is only a single disatcher instance per Silverlight application. This instance is accessible via any DependencyObject or ScriptObject instances' Dispatcher property. Once you have a reference to a dispatcher, you can use its BeginInvoke method to dispatch your work. In Silverlight we added an overload which takes an Action, which means you don't need to add a cast or anything to help the compiler infer what type of delegate you want to pass:

C#:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 

var myThread = new Thread(() => {
    // Using a lambda...
    myTextBlock.Dispatcher.BeginInvoke(() => myTextBlock.Text = "Updated from a non-UI thread.");

    // Using an anonymous delegate...
    myTextBlock.Dispatcher.BeginInvoke(delegate {
        myTextBlock.Text = "Updated from a non-UI thread.";
    });
});
myThread.Start();

Please note that you may not be able to find the dispatcher property via intellisense. It's marked as an advanced property, so you either need to update your VS settings to display advanced members, or you just need to ignore intellisense and assume your code will in fact compile regardless of what intellisense implies. The same goes for CheckAccess, which is actually marked as a member that should never be displayed. The main reason these members aren't always visible is because they shouldn't be as common as the other members on a DependencyObject. As I mentioned before, you'll probably want to use a BackgroundWorker most of the time instead.

Gotchas

There are a couple of things to be aware of. The first is that we try to guard against cross-thread invocations when this would potentially be unsafe. For example, we don't allow you to call into the HTML DOM or a JavaScript function from a background thread. The reason for this is that both assume to be invoked on the UI thread. Breaking this assumption can lead to unexpected behavior, including browser crashes.

The other thing to be aware of is creating deadlocks. Silverlight comes with primitives such as Monitor (encapsulated via the lock construct in C#) and ManualResetEvent which make it trivial to create a deadlock. A deadlock will cause most browsers to hang completely. While technically this isn't very different from some JavaScript that infinitely, it's often easier to accidentally create a deadlock than an infinite loop of code. For example, I've seen several people try to create a synchronous version of HttpWebRequest by letting the current thread wait for a ManualResetEvent to be notified by the response callback. HttpWebRequests however execute their callbacks on the UI thread, which means you have a deadlock right there. While ideally you avoid blocking the UI thread entirely, you should at least consider specifying timeouts when you use a synchronization object. For example, instead of the lock construct in C# (Monitor.Enter/Exit), consider using Monitor.TryEnter/Exit passing in a reasonable timeout, and instead of using ManualResetEvent's parameterless WaitOne, consider using one of the overloads.

You've hit the nail on the head with this topic actually.

I've been through exactly what you describe here with tryign to get HttpWebRequest's events to update the UI and didn't have much luck. The transfers went fine but because of hte doubly async nature of these calls and the fact that the UI doesn't update until an idle state is reached I never got the effect I was hoping to achieve.

(I know you have your upload component, but this is more for my own understanding of the issue than anything else <g>)

I really hope you guys reexamine the typical use case for HttpWebRequest and make that easier. Right now with async for *both* send and receive it takes a fair bit of code to make an HTTP call that requires both POST and retrieval. Data retrieval is one of the most common scenarios SL apps will have to deal with and this should be as straight forward as possible.
Yeah, HttpWebRequest is a fairly unfriendly API - especially when doing asynchronous requests (which is all you can do in Silverlight). I believe one of the plans is to extend WebClient and basically use that to provide a higher-level API for HttpWebRequest (using an event-based async pattern, instead of the Begin/End async pattern). Does that sound more reasonable?

In the meantime you might want to take a look at the code I put together in my previous post. The "Request" type should make it a little easier to make asynchronous requests in a slightly more natural way. It also allows you to just pass in a string of POST data, as well as passing in a callback that you can use for streaming POST data. (Well, technically it doesn't stream as the underlying APIs we use don't support true streaming of POSt data.)
In Beta 2, threading anything on the UI thread provides no help.

It may delay the action, but when the action occurs, it will freeze the UI until it finishes.

I have a datagrid that takes a second or two to load, and when it does, NOTHING can be happening at that time, there is a short freeze, and once loaded, everything is back to normal.

This behavior doesn't make sense.
Hey Wilco,

I created a background worker thread that creates a new Canvas instance. This raises the 'cross-thread access violation' Exception. I assume this is because when the Canvas is instantiated, the Dispatcher cannot be accessed because it is on the UI thread.

I need to do this because I want to create a tree of UIElement's in advance, so I can switch visual content swiftly as necessary. I load the visual's asynchronously. If I don't do it like this, the UI Thread is waiting on UIElement's to complete their construction. And because it's a large amount of these content's I moved to asynchronous compositioning of these elements.

Now I created a static property called Dispatcher, so I could access the Dispatcher from any class. This works. But how can I be sure that the piece of dispatched code has been executed? (to prevent race conditions)

C#:
1 

Controller.Dispatcher.BeginInvoke(() => uielement = new Canvas());



Any thoughts or even a better solution for this.

Grtz,
Tonny

btw. are you dutch?
Your message will be encoded/formatted when it is displayed. If you want to post code, please put the code inside [code=X][/code] tags, where X is the language of your code (C#, ASPX, SQL, etc).
Name:
Email:
(will be encoded using JavaScript to keep it functional and prevent it from being picked up by spammers)
Url:
 
Message:
3 + 3 =