Implement an Async timeout in Silverlight? - silverlight

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());

Related

Observable.Timer(DateTimeOffset) Process Exit

I have a Observable.Timer(TimeSpan) multiple times, but in couple of places I have used Observable.Timer(DateTimeOffset) to trigger the event at that time, but I believe it is stopping my process from exiting.
DateTimeOffset offset = new DateTimeOffset(minStart);
Observable.Timer(offset)
.Subscribe(_ =>
{
UpdateActive();
});
This piece of code is in my ViewModel and on Window Closed, the process is still running in the background, normally wherever I use the Observable.Timer(TimeSpan) they gets disposed automatically, why doesn't this?
Am I doing something wrong or is it a bug? Or am I missing something?
Given that you're using one of the Subscribe() extension methods, assuming you're using a recent version of RX, the observable should be releasing any subscribers when it completes. Is your observable completing in one case but not the other?
If your observable has not completed (i.e. if the time represented by offset hasn't happened yet) by the time you close your window, nothing is going to automatically unsubscribe for you. Here's what the introtorx site has to say on this matter (emphasis mine):
Considering this, I thought it was prudent to note that subscriptions
will not be automatically disposed of. You can safely assume that the
instance of IDisposable that is returned to you does not have a
finalizer and will not be collected when it goes out of scope. If you
call a Subscribe method and ignore the return value, you have lost
your only handle to unsubscribe. The subscription will still exist,
and you have effectively lost access to this resource, which could
result in leaking memory and running unwanted processes.
Using the overload of Observable.Timer that accepts DateTimeOffset will not on it's own cause a process to be held open; something else is responsible for this.
However, the consequence of not disposing subscriptions to Observable.Timer is that you will leak the timer resource.
You should retain the IDisposable subscription handles for timer and event based observables and dispose them appropriately; most WPF frameworks provide a suitable event for this.
In general, I track and dispose of all my window-scoped subscriptions, just to be on the safe side. See Convert Polling Web Service to RX for an example.

Asynchronous WCF Services in WPF - events

I am using WCF services asynchronously in a WPF application. So I have class with all the web service. The view models call the method in this proc, which in-turn calls the web service.
So the view Model code looks like this:
WebServiceAgent.GetProductByID(SelectedProductID, (s, e)=>{States = e.Result;});
And the WebService agent looks like:
public static void GetProductByID(int ProductID, EventHandler<GetProductListCompletedEventArgs> callback)
{
Client.GetProductByIDCompleted += callback;
Client.GetProductByIDAsync(ProductID);
}
Is this a good approach? I am using MVVM light toolkit. So the View Model static, so in the lifetime of the application, the view model stays. But each time the view model calls this WebServiceAgent, I think I am registering an event. But that event is not being unregistered.
Is this a problem. Lets say the view Model is called for 20 - 30 times. I am inserting some kind of memory leak?
Some helpful information, based on the mistakes I learned from myself:
The Client object seems to be re-used all the time. When not unregisering event handlers, they will stack up when future invokations of the same operations finish and you'll get unpredictable results.
The States = e.Result statement is executed on the event handler's thread, which is not the UI dispatcher thread. When updating lists or complex properties this will cause problems.
In general not unregistering event handlers when they are invoked is a bad idea as it will indeed cause hard to find memory leaks.
You should probably refactor to create or re-use a clean client, wrap the viewmodel callback inside another callback that will take care of unregistering itself, cleaning up the client, and invoking the viewmodel's callback on the main dispatcher thread.
If you think all this is tedious, check out http://blogs.msdn.com/b/csharpfaq/archive/2010/10/28/async.aspx and http://msdn.microsoft.com/en-us/vstudio/async.aspx. In the next version of C# an async keyword will be introduced to make this all easier. A CTP is available already.
Event handlers are death traps and you will leak them if you do not "unsubscribe" with "-=".
One way to avoid is to use RX (Reactive Extensions) that will manage your event subscriptions. Take a look at http://msdn.microsoft.com/en-us/data/gg577609 and specifically creating Observable by using Observable.FromEvent or FromAsync http://rxwiki.wikidot.com/101samples.
This is unfortunaltely not a good approach.
I learned this the hard way in silverlight.
Your WebserviceAgent is probably a long-life object, whereas the model or view is probably short-life
Events give references, and in this case the webservice agent, and wcf client a reference to the model. A long lifeobject has a reference to a short life object, this means the short life object will not be collected, and so will have a memory leak.
As Pieter-Bias said, the async functionality will make this easier.
Have you looked at RIA services? This is the exact problem that RIA services was designed to solve
Yes, the event handlers are basically going to cause a leak unless removed. To get the near-single line equivalent of what you're expressing in your code, and to remove handlers you're going to need an instance of some sort of class that represents the full lifecycle of the call and does some housekeeping.
What I've done is create a Caller<TResult> class that uses an underlying WCF client proxy following this basic pattern:
create a Caller instance around an existing or new client proxy (the proxy's lifecycle is outside of the scope of the call to be made (so you can use a new short-lived one or an existing long-lived one).
use one of Caller's various CallAsync<TArg [,...]> overloads to specify the async method to call and the intended callback to call upon completion. This method will choose the async method that also takes a state parameter. The state parameter will be the Caller instance itself.
I say intended because the real handler that will be wired up will do a bit more housekeeping. The real callback is what will be called at the end of the async call, and will
check that ReferenceEquals(e.UserState, this) in your real handler
if not true, immediately return (the event was not intended to be the result of this particular call and should be ignored; this is very important if your proxy is long lived)
otherwise, immediately remove the real handler
call your intended, actual callback with e.Result
Modify Caller's real handler as needed to execute the intended callback on the right thread (more important for WPF than Silverlight)
The above implementation should also have separate handlers for cases where e.Error is non-null or e.Cancelled is true. This gives you the advantage of not checking these cases in your intended callback. Perhaps your overloads take in optional handlers for those cases.
At any rate, you end up cleaning up handlers aggressively at the expense of some per-call wiring. It's a bit expensive per-call, but with proper optimization ends up being far less expensive than the over-the-wire WCF call anyway.
Here's an example of a call using the class (you'll note I use method groups in many cases to increase the readability, though HandleStuff could have been result => use result ). The first method group is important, because CallAsync gets the owner of that delegate (i.e. the service instance), which is needed to call the method; alternatively the service could be passed in as a separate parameter).
Caller<AnalysisResult>.CallAsync(
// line below could also be longLivedAnalyzer.AnalyzeSomeThingsAsync
new AnalyzerServiceClient().AnalyzeSomeThingsAsync,
listOfStuff,
HandleAnalyzedStuff,
// optional handlers for error or cancelled would go here
onFailure:TellUserWhatWentWrong);

Background processing on UI thread? (Winforms)

Is there a (or, do you have your own) preferred way to do background processing in slices on the UI thread in Windows Forms? Like OnIdle() in MFC?
In native Windows programming you could roll your own message loop to do this, but Application.Run() doesn't give us access to the message loop.
The Application.Idle event gives us no way to trigger it repeatedly.
I guess you could call native PostMessage() with P/Invoke (since there's no managed version) to post yourself a private "WM_IDLE" message, and override WndProc() to catch it. I don't know how this would get along with Application.Run().
So far I've used a short Timer for this, but I'm afraid I may be losing cycles sleeping, especially since the actual Timer resolution is coarser than the nominal 1 ms minimum.
The best option I've seen is to use a modified version of the Managed DirectX Render Loop designed by Tom Miller. By adding a call to Thread.Sleep() inside the render loop, you can pull your CPU usage down dramatically.
This does require a P/Invoke call to track that the application is still idle, but as long as it's idle, you can make a "timer" that fires continuously during the idle phases, and use that to do your processing.
That being said, on modern systems, you almost always have extra cores. I would suggest just doing the processing on a true background thread.
I thought of my own possible answer, inspired by Reed's talk of multithreading. I may have a way to retrigger Application.Idle:
Create a hidden form, let's call it formRetrigger.
In Application.Idle, launch my Retrigger() method on a thread pool thread.
Retrigger() calls formRetrigger.InvokeOnClick() (or any of the other "Control.Invoke" methods). I expect this to launch another message through Application's queue, causing Idle to get triggered again.

How can I know on the client side when the HTTP handler is done processing?

Probably a long question for a simple solution, but here goes...
I have a custom made silverlight control for selecting multiple files and sending them to the server. It sends files to a general handler (FileReciever.ashx) using the OpenWriteAsync method of a WebCLient control.
Basically, the silverlight code does something like this for each file:
WebClient client = new WebClient();
client.OpenWriteCompleted += (sender, e) =>
{
PushData(data, e.Result);
e.Result.Close();
data.Close();
};
client.OpenWriteAsync(handlerUri);
The server side handler simply reads the incoming stream, and then does some more processing with the resulting byte array.
THE PROBLEM is that client side OpenWriteCompleted is done as soon as all the data has been sent over the wire. My code will then contine with the next file. What I really want is to wait until the ASHX handler has finished with all it's processing of that request. How do I do that? Any wait mechanism on WebClient? Any callback I can do on the HttpContext in the handler? Should I use some other kind of transfer technique? Please advice!
The same question has been asked in Silverlight forums. The Microsoft endorsed answer was that you can't do that with WebClient and OpenWriteAsync. You need to either user UploadStringAsync or an HttpWebRequest.
Hrm, maybe a simple solutioin could be to tag the url with a GUID(the guid being unique per file, or transfer, whatever makes sense to your situatuation). Then you can have another simple web service that is capable of checking on the status of the other service, based on the guid, and have your silverlight client query that new service for its processing status(by passing the new web service the guid of the past transfer).
I'm assuming that you're concerned that the data being returned from the handler is taking a long time to transfer and the server is not being utilized during that time. There isn't a way to tell when the server is done processing, so I don't think you can do this without changing your architecture.
I would have your handler only an identifier of some sort (like a GUID or int) that can be used to retrieve the result of the handler in another request. So the page would call the handler, the handler would store the result and return the identifier, the page would call the handler the second time and call another handler to get the result of the first call. This would keep your server in use while your data was transferring.
Or you can probably do it with JavaScript (jQuery)... if you don't mind using JavaScript that is.
If files are not very big, and is feasible to keep each of them in memory, an ugly yet effective solution is converting them to strings and sending them using the UploadStringAsync method.
Avoid this approach if file size is unbounded, but if you can now that they will be relatively small, it is possible to use this approach.

In WinForms, why can't you update UI controls from other threads?

I'm sure there is a good (or at least decent) reason for this. What is it?
I think this is a brilliant question -
and I think there is need of a better
answer.
Surely the only reason is that there
is something in a framework somewhere
that isn't very thread-safe.
That "something" is almost every single instance member on every single control in System.Windows.Forms.
The MSDN documentation for many controls in System.Windows.Forms, if not all of them, say "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
This means that instance members such as TextBox.Text {get; set;} are not reentrant.
Making each of those instance members thread safe could introduce a lot of overhead that most applications do not need. Instead the designers of the .Net framework decided, and I think correctly, that the burden of synchronizing access to forms controls from multiple threads should be put on the programmer.
[Edit]
Although this question only asks "why" here is a link to an article that explains "how":
How to: Make Thread-Safe Calls to Windows Forms Controls on MSDN
http://msdn.microsoft.com/en-us/library/ms171728.aspx
Because you can easily end up with a deadlock (among other issues).
For exmaple, your secondary thread could be trying to update the UI control, but the UI control will be waiting for a resource locked by the secondary thread to be released, so both threads end up waiting for each other to finish. As others have commented this situation is not unique to UI code, but is particularly common.
In other languages such as C++ you are free to try and do this (without an exception being thrown as in WinForms), but your application may freeze and stop responding should a deadlock occur.
Incidentally, you can easily tell the UI thread that you want to update a control, just create a delegate, then call the (asynchronous) BeginInvoke method on that control passing it your delegate. E.g.
myControl.BeginInvoke(myControl.UpdateFunction);
This is the equivalent to doing a C++/MFC PostMessage from a worker thread
Although it sounds reasonable Johns answer isn't correct. In fact even when using Invoke you're still not safe not running into dead-lock situations. When dealing with events fired on a background thread using Invoke might even lead to this problem.
The real reason has more to do with race conditions and lays back in ancient Win32 times. I can't explain the details here, the keywords are message pumps, WM_PAINT events and the subtle differences between "SEND" and "POST".
Further information can be found here here and here.
Back in 1.0/1.1 no exception was thrown during debugging, what you got instead was an intermittent run-time hanging scenario. Nice! :)
Therefore with 2.0 they made this scenario throw an exception and quite rightly so.
The actual reason for this is probably (as Adam Haile states) some kind of concurrency/locky issue.
Note that the normal .NET api (such as TextBox.Text = "Hello";) wraps SEND commands (that require immediate action) which can create issues if performed on separate thread from the one that actions the update. Using Invoke/BeginInvoke uses a POST instead which queues the action.
More information on SEND and POST here.
It is so that you don't have two things trying to update the control at the same time. (This could happen if the CPU switches to the other thread in the middle of a write/read)
Same reason you need to use mutexes (or some other synchronization) when accessing shared variables between multiple threads.
Edit:
In other languages such as C++ you are
free to try and do this (without an
exception being thrown as in
WinForms), but you'll end up learning
the hard way!
Ahh yes...I switch between C/C++ and C# and therefore was a little more generic then I should've been, sorry... He is correct, you can do this in C/C++, but it will come back to bite you!
There would also be the need to implement synchronization within update functions that are sensitive to being called simultaneously. Doing this for UI elements would be costly at both application and OS levels, and completely redundant for the vast majority of code.
Some APIs provide a way to change the current thread ownership of a system so you can temporarily (or permanently) update systems from other threads without needing to resort to inter-thread communication.
Hmm I'm not pretty sure but I think that when we have a progress controls like waiting bars, progress bars we can update their values from another thread and everything works great without any glitches.

Resources