DownloadStringComplete has no arguments set? - silverlight

Normally I can find an answer to my problems here, but not this time, so I'll try asking a question. The issue: trying to use DownloadStringAsync in Silverlight 5.0. I do the call using:
System.Net.WebClient wc = new System.Net.WebClient();
wc.DownloadProgressChanged += wc_DownloadProgressChanged;
wc.DownloadStringCompleted += wc_DownloadStringComplete;
wc.AllowReadStreamBuffering = true;
wc.DownloadStringAsync(new Uri(baseURI));
(BTW this is in the public MainPage routine so it runs on loading the app).
My wc_DownloadProgressChanged function is called with no problem at all, and reports that 153 bytes have been received. (This is correct, I've checked the packets arriving using Wireshark, the data arrives and an ACK is sent just as expected.)
However the wc_DownloadStringComplete function, which starts like this:
void wc_DownloadStringComplete
(object sender,
System.Net.DownloadStringCompletedEventArgs e)
{
MessageBoxResult res;
try
{
if (e.Error == null && e.Result != null)
{
....
}
always generates an error and execution falls through to the catch block. Any attempt to access the DownloadStringCompletedEventArgs e variable causes an error: Unhandled Error in Silverlight Application Object reference not set to an instance of an object at CircuitTheory.MainPage.wc_DownloadStringComplete(Object sender, DownloadStringCompletedEventArgs e).
It looks to me as if the system is calling my wc_DownloadStringComplete function without setting the DownloadStringCompletedEventArgs parameter e. But that's impossible, isn't it?
Any ideas what I might be doing/understanding wrong? And how can I get the received data when e is not set to anything?

Related

WCF/Silverlight: How can I foul a Channel?

I was told that I shouldn't cache channels in Silverlight/WCF because they may become faulted and unsuable. Can somone show me some sample code that would prove it can happen.
Call a service to prove the connection can work (i.e. no bogus URL)
Make a second call that fouls the channel by causing it to go into a faulted condition
Repeat the first call, which would fail.
In my own testing, the key is whether the binding you're using is session-oriented or not. If you're using a stateless binding like BasicHttpBinding, you can muck up the channel all you want and you're good. For instance, I've got a WCF service using the BasicHttpBinding that looks like this -- note specifically the Channel.Abort() call in SayGoodbye():
public class HelloWorldService : IHelloWorldService
{
public string SayHello()
{
return "Hello.";
}
public string SayGoodbye()
{
OperationContext.Current.Channel.Abort();
return "Goodbye.";
}
}
And the Silverlight client code looks like this (ugly as hell, sorry).
public partial class ServiceTestPage : Page
{
HelloWorldServiceClient client;
public ServiceTestPage()
{
InitializeComponent();
client = new HelloWorldServiceClient();
client.SayHelloCompleted += new EventHandler<SayHelloCompletedEventArgs>(client_SayHelloCompleted);
client.SayGoodbyeCompleted += new EventHandler<SayGoodbyeCompletedEventArgs>(client_SayGoodbyeCompleted);
client.SayHelloAsync();
}
void client_SayHelloCompleted(object sender, SayHelloCompletedEventArgs e)
{
if (e.Error == null)
{
Debug.WriteLine("Called SayHello() with result: {0}.", e.Result);
client.SayGoodbyeAsync();
}
else
{
Debug.WriteLine("Called SayHello() with the error: {0}", e.Error.ToString());
}
}
void client_SayGoodbyeCompleted(object sender, SayGoodbyeCompletedEventArgs e)
{
if (e.Error == null)
{
Debug.WriteLine("Called SayGoodbye() with result: {0}.");
}
else
{
Debug.WriteLine("Called SayGoodbye() with the error: {0}", e.Error.ToString());
}
client.SayHelloAsync(); // start over
}
}
And it'll loop around infinitely as long as you want.
But if you're using a session-oriented binding like Net.TCP or HttpPollingDuplex, you've got to be much more careful about your channel handling. If that's the case, then of course you're caching your proxy client, right? What you have to do in that instance is to catch the Channel_Faulted event, abort the client, and then recreate it, and of course, re-establish all your event-handlers. Kind of a pain.
On a side note, when it comes to using a duplex binding, the best approach that I've found (I'm open to others) is to create a wrapper around my proxy client that does three things:
(1) Transforms the obnoxious event-raising code generated by the "Add Service Reference" dialog box into a far-more-useful continuation-passing pattern.
(2) Wraps each of the events raised from the server-side, so that the client can subscribe to the event on my wrapper, not the event on the proxy client itself, since the proxy client itself may have to be deleted and recreated.
(3) Handles the ChannelFaulted event, and (several times, with a timeout) attempts to recreate the proxy client. If it succeeds, it automatically resubscribes all of its event wrappers, and if it fails, it throws a real ClientFaulted event which in effect means, "You're screwed, try again later."
It's a pain, since it seems like this is the sort of thing that should have been included with the MS-generated code in the first place. But it sure fixes a whole lot of problems. One of these days I'll see if I can get this wrapper working with T4 templates.

Why the form load can't catch exception?

Is this a bug in Winforms? (tested on both VS2008 and VS2010)
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Hey");
}
I don't receive any error in that code, awhile ago, I'm trying to formulate a solution for this question Parse a number from a string with non-digits in between
And I do this code in Form1_Load:
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("X");
string s = "12ACD";
string t = s.ToCharArray().TakeWhile(c => char.IsDigit(c)).ToArray().ToString();
MessageBox.Show("Y");
int n = int.Parse(t);
MessageBox.Show(n.ToString());
}
I wonder why it didn't show the number. Then on moving the code to button1_Click...
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("X");
string s = "12ACD";
string t = s.ToCharArray().TakeWhile(c => char.IsDigit(c)).ToArray().ToString();
MessageBox.Show("Y");
int n = int.Parse(t);
MessageBox.Show(n.ToString());
}
...then I noticed that there's an error: Input string was not in a correct format.
Why Form1_Load didn't catch any exception, why it silently fail? The code just exit out of form1_load at string t = s.ToCharArray().TakeWhile...
Rewrite, I've since figured out where it comes from. Windows misbehaves when an exception is raised in a 32-bit process when it runs on a 64-bit version of Windows 7. It swallows any exception raised by code that runs in response to a Windows message that's triggered by the 64-bit windows manager. Like WM_SHOWWINDOW, the message that causes the Load event to get raised.
The debugger plays a role because when it is active, normal exception trapping in a Winforms app is turned off to allow the debugger to stop on an exception. That doesn't happen in this scenario because Windows 7 swallows the exception first, preventing the debugger from seeing it.
I've written about this problem more extensively in this answer, along with possible workarounds.
See this: The case of the disappearing OnLoad exception. It's by-design (though by-extremely-stupid-design, IMO). Your exception is hitting a kernel-mode boundary during the unwinding of the stack. If you can, switch to some other event, or don't let exceptions escape; this doesn't help if you're expecting your debugger to automatically break on an un-handled exception in OnLoad.
If you care, I wrote a bit more in this answer.
The WinForms framework classes won't automatically catch any exceptions for you. That isn't a bug, it's by design - what would they do with the exception?
You have to have your own try/catch block in any event or alternatively handle the Application.ThreadException event. That event can be helpful for some generic handling code like logging the exception or displaying an error dialog, but obviously it can't do anything specific to any individual event or exception type.

How to stop the running wcf services in silverlight when exception happens

After some digging into exception handling in silverlight and reading some useful blogs like this
Silverlight exception handling using WCF RIA Services and WCF Services I ended up implementing similar idea in the App.xaml.cs to show an error page and call another wcf service method to log the error to the event viewer:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (!System.Diagnostics.Debugger.IsAttached)
{
var errorPage = new Error();
errorPage.Show();
string errorMsg = string.Format("{0} {1}", e.ExceptionObject.Message, e.ExceptionObject.StackTrace);
EventHandler<WriteIntoEventLogCompletedEventArgs> callback = (s, ev) =>
{
bool result = ev.Result;
};
(new ServiceProxy<ApplicationServiceClient>()).CallService<WriteIntoEventLogCompletedEventArgs>(callback, errorMsg);
e.Handled = true;
}
}
and this is what I have in Error.xaml.cs:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
that basically will close the error page when user clicks on OK.
Everything works fine most of the cases.The problem happens when one of the callbacks to the wcf service cause an exception.The error page will be shown nicely and when user clicks ok, error page will get closed. But the background is still showing the busy indicator and the original service callback is still waiting for the response.I need to somehow terminate it.
I would be appriciative if anybody could help.
Thanks,
Sil
--
Thanks a lot for your helpful reply.I used the same idea and in the original service callback method added a code to check e.Error and if it is not null,close the window(it is a child window) with the busyindicator and everything works perfect now. Thanks again. Sil
My guess is that the original service callback may be completing but in an error condition. You may need to detect the error condition and set the IsBusy property of the busyindicator back to False.
Couple of things to check
Is the original service callback atleast returning successfully? You can check this by placing a breakpoint into the original service callback method.
Have you correctly handled the error condition in your callback method. For example -
void proxy_GetUserCompleted(object sender, GetUserCompletedEventArgs e)
{
if (e.Error != null)
{
getUserResult.Text = "Error getting the user.";
}
else
{
getUserResult.Text = "User name: " + e.Result.Name + ", age: " + e.Result.Age + ", is member: " + e.Result.IsMember;
}
}
Reference - http://msdn.microsoft.com/en-us/library/cc197937(v=VS.95).aspx

Form Dispose() or Close()

I'm having 2 forms. From one form I created and shown the other form. It's working great. But when I try to close or Dispose that form from the form that created it I get following Exception:
Exception :
Value Dispose() cannot be called while doing CreateHandle().
Stack Trace :
========================
at System.Windows.Forms.Control.Dispose(Boolean disposing)
at System.Windows.Forms.Label.Dispose(Boolean disposing)
at System.ComponentModel.Component.Dispose()
at System.Windows.Forms.Control.Dispose(Boolean disposing)
at System.Windows.Forms.ContainerControl.Dispose(Boolean disposing)
at System.Windows.Forms.Form.Dispose(Boolean disposing)
at Speedometer_Application.frmSpeedometer.Dispose(Boolean disposing)
Any idea????
The error Value Close() cannot be called while doing CreateHandle() usually happens when we try to close the form in the constructor or Load event.
For example, the following code gives the error:
private void frmCustomer_Load(object sender, EventArgs e)
{
if (!Valid())
this.Close;
}
The Solution:
private void frmCustomer_Load(object sender, EventArgs e)
{
if (!Valid())
this.BeginInvoke(new MethodInvoker(Close));
}
You can use this in your code.
it is hard to say what is the problem from the code you posted.
The code that you posted should work (form shown with Show() should be possible to close with Dispose() method).
The reason why it does not work is probably somewhere in the form that you are trying to dispose of. When you call Dispose() method (according to the error message this is what happens) on an object, that object will try to dispose of all its children and do some cleanup. That is the place to look for error.
My suggestion is to comment out all your code in the form objfrm (or make new EMPTY form) and see if error happens. It should not happen. Then start adding commented code and see when the error happens. I bet it will be in the code that is being called as consequence of Dispose method.
The code is as follows:
if (frmMain.objfrm== null)
{
frmMain.objfrm = frmMyForm.Instance;
frmMain.objfrm.ShowInTaskbar = false;
}
frmMain.objfrm.Show();
frmMain.objfrm.BringToFront();
frmMain is the Main Form that has a static variable of the frmMyForm. than in my code whereever i want to use this I just check if it's not null than create it using a static Instance and than give the peoperty.
While closing the form I have the following code:
frmMain.objfrm.Close_this();
The Close_this calls the Close() or Dispose() method.
But when I call that function I get the above exception.
You need to use ShowDialog instead of Show thats the problem. Show dont block the application and the code keeps running.
You are disposing the object when the GUI is creating it (that what the exception said)
Try with this:
if (frmMain.objfrm== null)
{
frmMain.objfrm = frmMyForm.Instance;
frmMain.objfrm.ShowInTaskbar = false;
}
frmMain.objfrm.ShowDialog();
Note the ShowDialog()

WPF - DispatcherUnhandledException does not seem to work

I started a new WPF project in VS2008 and then added some code to trap DispatcherUnhandledException. Then I added a throw exception to Window1
but the error is not trapped by the handler. Why?
public App()
{
this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
System.Windows.MessageBox.Show(string.Format("An error occured: {0}", e.Exception.Message), "Error");
e.Handled = true;
}
void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
throw new NotImplementedException();
}
This can happen because of the way you have the debugger handling exceptions -- Debug/Exceptions... should allow you to configure exactly how you want it handled.
Look at following msdn link http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx
Following is Relevant here
If an exception is not handled on either a background user interface (UI) thread (a thread with its own Dispatcher) or a background worker thread (a thread without a Dispatcher), the exception is not forwarded to the main UI thread. Consequently, DispatcherUnhandledException is not raised. In these circumstances, you will need to write code to do the following:
Handle exceptions on the background thread.
Dispatch those exceptions to the main UI thread.
Rethrow them on the main UI thread without handling them to allow DispatcherUnhandledException to be raised.
This is how I handle it. This isn't pretty but keep in mind that this type of error should never make it past debugging as a dev. Those errors should be long resolved before you go to production (so its okay that this isn't pretty). In the Startup project, in the App.xaml (App.xaml.cs) code behind, I put the following code.
OnStartup, create a DispatcherUnhandledException event handler
In the handler, use a MessageBox to display the message. Note that its likely the startup window has not yet been created so don't try to put it in a window.
e.Handle the error
I like to see when there are additional internal errors so I continue to call the display window until the internal error is null.
I'm not sure why the code block special characters aren't formatting this correctly. Sorry about that.
protected override void OnStartup(StartupEventArgs e)
{
// define application exception handler
Application.Current.DispatcherUnhandledException +=
AppDispatcherUnhandledException;
// defer other startup processing to base class
base.OnStartup(e);
}
private void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
runException(e.Exception);
e.Handled = true;
}
void runException(Exception ex)
{
MessageBox.Show(
String.Format(
"{0} Error: {1}\r\n\r\n{2}",
ex.Source, ex.Message, ex.StackTrace,
"Initialize Error",
MessageBoxButton.OK,
MessageBoxImage.Error));
if (ex.InnerException != null)
{
runException(ex.InnerException);
}
}
At first, even outside the debugging environment, my handler does not seem to be triggering.....then I realized I forget to set e.Handled = true.
In truth it was working but because e.Handled was still false the standard exception handler still kicked in and did its thing.
Once I set e.Handled = true, then everything was hunky dory. So if its not working for you, make sure you've done that step.
For those interested
It seems that the IDE is still breaking on exceptions and that if you click continue in the IDE it call the error handler.

Resources