This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Execute a WebRequest in a Background thread while UI Thread is blocked
Check out this code:
Thread t = new Thread((a) =>
{
var client = new WebClient();
client.DownloadStringAsync(new Uri("http://www.google.com"));
bool pointB = true;
});
t.Start();
t.Join(10000);
When this is run on the UI thread in Silverlight, even though DownloadStringAsync() is called quickly, pointB will not be reached until after the Join() times out. This means DownloadStringAsync() must somehow require the UI thread to do its work. Note: this has nothing to do with the callback to DownloadString. I know that WebClient's callbacks happen on the UI thread (see here: Silverlight Background Thread using WebClient).
The behavior of my code seems to indicate that the async invoke method itself (DownloadStringAsync()) also requires the UI thread. Is that right? And if so, why? I also want to note this same behavior is exhibited when using HttpWebRequest.BeginGetResponse()
Edit: to make things crystal clear, the order of operations I see when I step through this code is
t.Start()
t.Join(10000);
var client = new WebClient();
client.DownloadStringAsync(new Uri("http://www.google.com"));
(... Join() timeout)
bool pointB = true;
Alright, I think I figured out the answer after a little more digging. It does seem indeed that all network code is ultimately run on the UI thread:
http://nondestructiveme.com/2010/11/23/silverlight-and-networking-the-ui-thread/
The good news is it seems Microsoft fixed this "bug", as you might be justified in calling it, in Silverlight 5:
http://msdn.microsoft.com/en-us/library/gg986857(VS.95).aspx
(At the bottom of the page under Performance Improvements:
"Reduced network latency by using a background thread for networking. This is helpful for scenarios that use client HTTP web requests.")
I'll edit this answer once I test my code on Silverlight 5 to see if it indeed fixed the issue.
Edit: Built against Silverlight 5 and I'm still having the same problem. I think it's time for me to give up trying to block the UI thread at all...
Related
In my console app I've been trying to start an STA thread and show a WPF window. I've succeeded showing the window, but I had issues with a library using Dispatcher (System.Reactive.Windows.Threading to be precised). I've fixed my problems using code from this doc - what I was missing was calling System.Windows.Threading.Dispatcher.Run() in the right moment.
But after reading this article carefully (and others) and examining Dispatcher's API I still don't know: how to tell WPF Dispatcher is correctly initialized and running? It'd be very useful for libraries requiring Dispatcher, if they could check it.
-- EDIT --
// Extending my question after #Peter Duniho remarks
Having C# console application I wanted to create a WPF window, where I'll observe, on Dispatcher, some data. The full code is here
So I have my program, where Main class looks like that:
static void Main(string[] args)
{
var observable = Observable
.Interval(TimeSpan.FromMilliseconds(500))
.TakeWhile(counter => counter < 10);
var thread = new Thread(() =>
{
new TestWindow(observable);
Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
Console.ReadKey();
}
I create here an observable with Interval operator, which ticks every 500 milliseconds, and I pass it to a TestWindow (code below) which I run on a separate thread. After 10 ticks I end the observable sequence.
TestWindow class:
public class TestWindow : Window
{
public TestWindow(IObservable<long> observable)
{
var isDispatcherInitialized = false;
Dispatcher.Invoke(() => isDispatcherInitialized = true, DispatcherPriority.ApplicationIdle);
if (!isDispatcherInitialized)
throw new ApplicationException("Dispatcher not initialized");
observable
.ObserveOnDispatcher()
.Window(TimeSpan.FromMilliseconds(600))
.Subscribe(_ => Console.WriteLine($"OnNext, observed on dispatcher with Window operator"));
}
}
In TestWindow I observe my observable on Dispatcher (ObserveOnDispatcher()), and I use Window operator.
PROBLEM with that code (tested on .NET Framework and on .NET Core 3.0 preview):
if I don't call Dispatcher.Run(); when starting STA thread, the validation where I call Dispatcher.Invoke() will be passed, but ObserveOnDispatcher() won't work correctly - subscription never stops, and the message: "OnNext, observed on dispatcher with Window operator" goes forever.
That's why I was wondering if I could detect Dispatcher's state.
It would be helpful if you would elaborate on this statement:
It'd be very useful for libraries requiring Dispatcher, if they could check it.
That is, why would it be useful?
For one, if you are using a third-party library (such as the Reactive Extensions (Rx) for .NET you mentioned, how would you knowing how to check for the dispatcher state help that library?
For another, what scenario doesn't work for you? Lacking a specific problem to solve, your question is fairly open-ended. It's not clear what type of answer would actually address your question.
That said, two things come to mind:
If you want to know if a dispatcher has been created for a given thread, you should call System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread); This will return null if not dispatcher has been created yet for that thread, or a reference to the dispatcher if it has been.
If you want to know that the dispatcher has completed initialization and is ready to dispatch things, it seems to me that the easiest thing to do is ask it to dispatch something, and when it does, it's ready. Using an overload of one of the invoking methods (BeginInvoke(), Invoke(), or InvokeAsync()) that takes a DispatcherPriority value, you can get fine-grained information regarding just what level of initialization has happened. For example, if you pass DispatcherPriority.Normal or DispatcherPriority.Send, when your delegate is invoked you'll know that the dispatcher is running. But if you pass DispatcherPriority.ApplicationIdle or DispatcherPriority.SystemIdle, you'll know that not only is the dispatcher running, but it's cleared its backlog of initial events to dispatch and the application is sitting waiting for user input.
I am supposed to work on a wpf legacy application( and desktop app is a new beast for me).
I have read that consumming task should not be launched on the ui thread : but I find this following code in the code behind of a view :
bool isSearching = true;
try
{
Task<ProductSearchResult>.Factory
.StartNew(() => DBCatalogService.Search( search.Criteria, search.CriteriaPage, search.CriteriaResultByPage)
.ContinueWith(res => LoadResult(res, search.Criteria, search.CriteriaPage, search.CriteriaResultByPage),
TaskScheduler.FromCurrentSynchronizationContext())
.ContinueWith(s => isSearching = false);
}
catch
{
...
}
I am wondering it will not cause any trouble.
I know that it's sounds weird to call the database directly from the view code behind, but I just want to know if it could freeze the ui thread or something like this.
Thank you for your advice on this matter.
My question is : does the sample code that I provided would block the UI thread and have to be considered harmfull or not ?
The call to the DBCatalogService.Search method will not block the UI thread since it is being invoked on a background thread using the task parallel library (TPL).
The call to the LoadResult method will however be executed on the UI thread once the task that calls the Search method has completed.
This is fine though since this method probably sets some properties of some UI elements based on the result of the search and you must do this on the UI thread. This is because WPF controls have thread affinity, meaning that a control can only be accessed on the thread on which it was originally created.
So no, the sample code you have provided should not be considered "harmfull" in terms of UI responsiveness assuming that the LoadResult doesn't perform any strange and potentially long-running operations.
If you block the UI thread (dispatcher thread) with a long-running operation such as a synchronous DB request, your application will be unresponsive until the thread is unblocked.
You can avoid this by either:
Doing the blocking/synchronous operation on another thread
Making the operation non-blocking/asynchronous
Both of the above
Using async/await can make your code read much like the synchronous form, but with asynchronous behaviour. It should be much clearer than the code sample you give in the question. However you need an async form of your search.
If you do use another thread, remember to dispatch back onto the UI thread if you have to update UI properties.
I'm wondering if there is some technique or method to detect calls in a WPF app that are not using async/await.
The reason I ask is that the WPF app I am working on is stuttering and halting on the screen updates, and I can't seem to track down the source of the calls that are blocking the GUI thread.
I am using VS2012 and VS2013 with the MVVM design pattern.
This doesn't answer your question directly but this will help with identifying when the dispatcher thread is overloaded, the following code uses an event handler around the DispatcherInactive event to calculate how long dispatcher thread has been overloaded (blocked) with work:
var maxThreshold = TimeSpan.FromMilliseconds(750);
var previous = DateTime.Now;
Application.Current.MainWindow
.Dispatcher.Hooks.DispatcherInactive += (sender, eventArgs) =>
{
var current = DateTime.Now;
var delta = current - previous;
previous = current;
if (delta > maxThreshold)
{
Debug.WriteLine("UI Freeze = {0} ms", delta.TotalMilliseconds);
}
};
I would suggest this is only ever used in debug mode, so it would be wrapped in a #if DEBUG block. You don't want this running in production.
I think a performance profiler could help you in this case.
I personally recommend ANTS profiler, you can download a trial and test your application with it. It would tell you where a certain period of the execution of your app is spending its time in.
Usually it is very easy to find what is blocking the UI. There can be 2 cases - either you are performing an expensive operation on the UI thread, you can test if the thread executing is the UI thread using:
if (Thread.CurrentThread == Dispatcher.CurrentDispatcher.Thread)
{
//UI Thread
}
Or, you are displaying to many controls and it takes long time to render. Usually the lists cause this when the list is not virtualizing items.
You can subscribe to events of the WPF dispatcher to track down your problem. The UI thread queues work items inside an object called a Dispatcher. The Dispatcher selects work items on a priority basis and runs each one to completion.
To monitor the Dispatcher you can e.g. subscribe to these operations:
Dispatcher.Hooks.OperationPosted += Hooks_OperationPosted;
Dispatcher.Hooks.OperationStarted += Hooks_OperationStarted;
Dispatcher.Hooks.OperationAborted += Hooks_OperationAborted;
You find a full list here.
Depending on your problem you might find yourself better of with a commercial profiler but quite often you get good results with just observing the dispatcher queue.
In Silverlight, say we start an async request:
var request = WebRequest.Create(uri);
and then wait for a response via a delegate
request.BeginGetResponse(getResponseResult => ...
How do we timeout this waitee, to deliver a time-out error signal to the delegate instead? Use a timer? (note: timeout options available in the .net framework are missing in the Silverlight version).
To handle two messages arriving at the same time, we could introduce a Guid filter, and then ignore a 2nd message when/if it was delivered to the delegate. Or in reverse (better), we register an expiring Guid so that the delegate can discard a second message -- at least some garbage collection is possible then (although the memory footprint of a delegate has got to be on the small side).
What follows are some notes I've made. I haven't reached a conclusion yet. Any help much appreciated.
My line of enquiry was going to be to implement a timer, notify the callback, and then somehow cancel waiting delegate in request.BeginGetResponse(...).
Note:
While the .Net Frame Work 4 implements a timeout on the WebRequest class, the Silverlight version does not.
"System.Threading.Task.Wait Method (TimeSpan)" is not available either
QUESTION 1: is there a better way to implement a timeout error to the same delegate target?
QUESTION 2: To cancel the waiting delegate, is it sufficient to use "request.BeginGetResponse(null)"?
QUESTION 3: will a non executed delegate (e.g. getResponseResult => ...) cause a small memory leak? Is this just a minor concern?
Information on creating a timer:
System.Windows.Threading.DispatcherTimer
http://blog.bodurov.com/How-to-Create-setTimeout-Function-in-Silverlight
Some References:
http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.opentimeout(v=VS.95).aspx (seems to be WCF related)
http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.receivetimeout(v=VS.95).aspx (seems to be WCF related)
http://blog.bodurov.com/How-to-Create-setTimeout-Function-in-Silverlight (could be useful)
Silverlight, dealing with Async calls (no new information)
http://petesbloggerama.blogspot.com/2008/07/omg-silverlight-asynchronous-is-evil.html (I want to deal with Async properly... I've got some good techniques, but I want to ensure that I'm using them cleanly. Probably I need to look into delegates more closely).
http://msdn.microsoft.com/en-us/library/dd460717.aspx#CommunityContent
http://csharperimage.jeremylikness.com/2010/03/sequential-asynchronous-workflows-in.html (some good information. Still haven't found out what to do about infinitely waiting delegates).
If you feel like giving reactive extensions a try you will get time out support for cheap. With Rx it will look something like this (not exact code):
var obsrv = Observable.FromAsyncPattern<...>(Begin..., End...);
obsrv(...).Timeout(new TimeSpan(0,0,5)).Subscribe(() => DoThings());
Here are the 2 ways we are using trying to use thread/dispatcher for multi tasking a few things:
I am wondering if anyone has any suggestions which one is better option.
Snippet 1:
Thread t = new Thread(new ThreadStart(delegate
{
MyMethod();
}));
t.IsBackground = true;
t.Start();
t.Join();
Snippet 2:
Dispatcher.CurrentDispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(dummyDelegate)delegate
{
MyMethod();
}
);
Please advise.
Thanks
N
Neither is "better": they are different.
The first example runs MyMethod on a background thread. So if MyMethod blocks, for example on network activity or doing something computation intensive, this doesn't block the UI thread, and the UI remains responsive. (Though since your sample code blocks and waits, you are currently losing this advantage anyway.) The downside is that MyMethod has to jump through some minor hoops if it wants to read or update the UI.
The second example runs MyMethod on the UI thread. This allows MyMethod to interact without restriction with elements in the UI, but is unsuitable if MyMethod takes a long time because it freezes the UI while MyMethod is running.
So it depends on what MyMethod does. If MyMethod updates a couple of UI elements and then exits, use the second option. If MyMethod loads files or downloads data, and/or performs lengthy computation, use the first.
There is also a third option: use the Threadpool to execute a short-lived asynchronous call. For example:
System.Threading.Threadpool.QueueUserWorkItem(
delegate(object context)
{
// context is unused
MyMethod();
});
This will use a thread from the threadpool to execute MyMethod. When the method completes, the thread will be returned to the pool. The advantage of this method is that you don't have to manage the lifetime of the threads yourself, and you don't incure the memory and performance overhead of creating and destroying the thread.
Anything wrong with using good ole BackgroundWorker?
It's not WinForms specific so you can still use it in WPF.