Reputation: 2417
DISCLAIMER: The following code is not something I would ever use in a real application. I stumbled on this problem and would like to know what's happening under the hoods.
Let's assume that for some crazy reason we had the following code...
using (System.Net.WebClient webClient = new System.Net.WebClient())
{
bool done = false;
webClient.UploadFileCompleted += (s, e) => done = true;
string uploadUri = "ftp://www.notarealurl.com/";
string file = @"temp.txt";
webClient.UploadFileAsync(
new Uri("ftp://www.notarealurl.com/"), "temp.txt");
while (!done)
{
System.Threading.Thread.Sleep(100);
}
}
This code works as expected in a simple console app. However, move it to a WPF app and it never exits the "while" loop. This through me for a loop for a while until it occured to me that this might be an issue with the events being dropped in the message pump and therefor not being processed. To test this, I modified the "while" loop like this...
while (!done)
{
System.Threading.Thread.Sleep(100);
// Processes all messages currently in the message queue
Dispatcher.Invoke(
DispatcherPriority.Background, new ThreadStart(delegate { }));
}
Sure enough, that fixed it. So,on to the question...
What is going on here? When I run this code in a console app the event handler is executed on a worker thread. Why/how does it get put on the main thread in WPF?
Upvotes: 1
Views: 2767
Reputation: 2417
Ok, I did a little decompiling with Reflector and I've worked out what's going on under the hoods. The web client makes use of a SynchronizationContext class to handle putting callbacks on the original thread. I was not familiar with the SynchronizationContext class, but there's a really nice article about it here...
http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx
Upvotes: 1
Reputation: 29594
Iמ WPF (and also in WinForms, Win32 and any other UI library I've ever worked with) you can only access a UI object from the same thread that created it.
Also, in any GUI Windows program you have a message loop and message dispatching, in a console application you don't.
So it looks like either
or
Upvotes: 1
Reputation: 8744
I think in WPF, it tries to put all callbacks on the thread that they came from. This is called the "affinity" of the thread.
Upvotes: 1