Click here to Skip to main content
15,881,381 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
INTRODUCTION AND RELEVANT INFORMATION:

I am an inexperienced C# developer that inherited colleague's project ( C#, .NET 3.5, Windows Mobile 6.5) and was tasked to fix certain bugs.

One of the tasks was to switch application to offline mode if Internet connection is unavailable. My colleague used OpenNetCF library to help him with the FTP connection part of the application, which makes things harder for me.

The problem lies in "login" form. This is the first thing user sees, and this form tries automatically to connect to server. If no connection is available, it simply stands idle, showing message "Connecting...".

PROBLEM:

My task is to switch to offline mode if connection is unavailable.

MY EFFORTS TO SOLVE THIS:

For further explanation, I feel it would be best to provide code for the login-form's onLoad event:
C#
// class fields:
delegate void StringDelegate(string value);
private FTP m_ftp;

private void dlgLoading_Load(object sender, EventArgs e)
{
    m_ftp = new FTP(address);
    m_ftp.ResponseReceived += new
        FTPResponseHandler(m_ftp_ResponseReceived);
    // m_ftp_Connected processes files in a certain way
    m_ftp.Connected += new FTPConnectedHandler(m_ftp_Connected);
    m_ftp.BeginConnect(username, password);
    // sets label's text to inform the user it is connecting
    lblText.Text += "Connecting...   ";
}


Debugging through code, I have found out that an exception SocketException has been thrown in another file that seems to belong to the OpenNETCF library. It's name is FTP.cs and the function ConnectThread throws it when trying to connect. ConnectThread is called by m_ftp.BeginConnect in the above code.

This is perfectly fine, because I haven't adjusted emulator to have Internet connection.

In JAVA, function can throw an exception.

Reading through C# books/tutorials, searching through Internet and here, I have found out that this can not be done in C#.

However, searching further, I have learned that in C# exceptions "bubble up" when not handled.

I have concluded that this might be good programming practice ( to "bubble up" the exception if you can't handle it ) based on this[^] thread.

Therefore, I have decided to "bubble up" the exception from the method in the library all the way to the code in my login-form. Then I could catch it, and continue from there in offline mode.

I have removed try/catch block from the relevant methods in the library/my code, and changed the above code to this:
C#
// class fields:
delegate void StringDelegate(string value);
private FTP m_ftp;

private void dlgLoading_Load(object sender, EventArgs e)
{
    try
    {
        m_ftp = new FTP(address);
        m_ftp.ResponseReceived += new
            FTPResponseHandler(m_ftp_ResponseReceived);
        // m_ftp_Connected processes files in a certain way
        m_ftp.Connected += new FTPConnectedHandler(m_ftp_Connected);
        m_ftp.BeginConnect(username, password);
        // sets label's text to inform the user it is connecting
        lblText.Text += "Connecting...   ";
    }
    catch( Exception ex )
    {
        MessageBox.Show( ex.Message );
        // i thought of adding a check at this place
        // if exception is SocketException 
        // so I can launch "offline code" here
    }
}


I hoped to catch the exception there but my program terminates. I am not sure, but this makes me think that exception doesn't get handled anywhere.

QUESTIONS:

* How can I properly "bubble up" this type of exception, in this scenario?

* Is my approach valid ( I remind you that I am very inexperienced)? Is there a better solution than my approach?

Being inexperienced, I apologize if I have omitted important information. Please leave a comment and I will edit my post as soon as possible.
Posted
Comments
Rob Philpott 22-Jan-15 9:16am    
I think the problem lies in the BeginConnect(). Methods that start 'Begin' imply use of the asynchronous programming model (APM), whereby the connection actually is handled by a background thread (sort of). Exceptions do 'bubble up', but only on the current thread. I think the exception is happening on a background thread. Do you have a Connect() without the Begin - if so try that and we can go from there....
Rob Philpott 22-Jan-15 9:26am    
Just as an extension to this. The idea with asynchronous methods is you kick them off and get on with other stuff and they call back to you when they're ready. I'm not familiar with the library you are using but it has events (callbacks) for being connected, data transferred etc. Does it have an event for errors?
AlwaysLearningNewStuff 22-Jan-15 9:53am    
Yes, as I have said in my post, it happens in background thread. Do you have a Connect() without the Begin No, there is no such option. Does it have an event for errors? No, I haven't found one.

It only has IsConnected property ( bool type). I am trying to adjust emulator for internet access at the moment. That way I could test if mentioned property is true or false, which would solve my problem.

I will update my post with newest findings as soon as I can.

Thank you for helping out. Best regards until we "hear" again.
johannesnestler 23-Jan-15 10:56am    
No, just checking the IsConnected property after calling BeginConnect is not enough, the flag will be set during BeginConnect (by the ConnectThread method), where the exception occurs. Even if no exception is raised it won't help cause BeginConnect returns to the caller while Connecting thrad is still running... See my answer...
AlwaysLearningNewStuff 23-Jan-15 11:58am    
I saw your answer and I agree with you => my approach will fail, sadly.

If there was only a way to let the exception "bubble up" ( in that thread ) and catch it in GUI thread...

Thank you for helping.

Hi,

I just had a quick look at http://ftp.codeplex.com/SourceControl/latest#FTP.cs[^] and the ConnectThread method - if it throws the exception it doesn't set the connected flag.

Some Solutions come to my mind:


*Try to wait for the connected flag (by calling FTP's CheckConnect method) to become true with some timeout (if timeout exceeded you assume connecting failed) - involves some kind of polling... not so good.
*Better: create some "ConnectionErrorOccured" Event and raise it on exception inside the ConnectThread method, then listen for the Event in your Form (pass needed exception Information along with your Event as Event data)
*Avoid the code running if you "know" before that you have no Internet Connection (not shure if this is so easy to check on CE...) - doesn't solve other connection Problems...

So I think the second solution would be best....

Just my 2c

Good Luck with your bug-Fixing...

Kind regards
Johannes
 
Share this answer
 
Hi again,

So here is some example code for my 2nd "idea" from solution1.

The idea is to extend the existing library code according to this:

C#
public class Library
{
    public event EventHandler<ErrorOccuredEventArgs> ErrorOccured;

    // internal method, this is the method running on a separate thread
    void ThreadMethod()
    {
        // Simulate some latency
        Thread.Sleep(5000);

        // Simulate exception
        try
        {
            throw new Exception("Sample Exception");
        }
        catch(Exception ex)
        {
            // Exception occured
            OnErrorOccured(new ErrorOccuredEventArgs(ex));
        }
    }

    // call this to start the thread
    public void StartThread()
    {
        Thread thread = new Thread(ThreadMethod);
        thread.Start();
    }

    // Just raises the event, it's good style to do this in a dedicated method, so inherited classes can "disable" raising the event (proteced virtual)
    protected virtual void OnErrorOccured(ErrorOccuredEventArgs eoea)
    {
        EventHandler<erroroccuredeventargs> handler = ErrorOccured;
        if (handler != null)
            handler(this, eoea);
    }
}

// EventArgs implementation used as parameter for the ErrorOccured event.
public class ErrorOccuredEventArgs : EventArgs
{
    public ErrorOccuredEventArgs(Exception ex)
    {
        Exception = ex;
    }

    public Exception Exception { get; private set; }
}


Steps are:
1. Create a new event (here i called it ErrorOccured)
2. Create an EventArgs implementation for the generic EventHandler delegate (as alternative you could create your own delegate) used as handler-type for the Event.
3. Create a dedicated method to raise the Event (this is just good coding style, don't raise events directly from variouse places in your code)
4. On all places where the exceptions occurs, raise the event with the thrown exception as parameter (via EventArgs)- in above example an exception is always thrown.

The caller code then will look something like this:
C#
   Library lib = new Library();
            lib.ErrorOccured += lib_ErrorOccured;
            lib.StartThread();

...

void lib_ErrorOccured(object sender, ErrorOccuredEventArgs e)
        {
            MessageBox.Show(e.Exception.Message);
        }


In the same way you could create an Event "ConnectionEstablished", "TimoutOccured" or whatever you like.
In the end you will attach the handlers from you Login-Forms code, start the thread and wait for Error or ConnectionOk(...) events. Inside the handlers for these events you set your state (Error = No Connection, Success = connecting ok)

Be Aware that there are other ways to handle this kind of problem (you could raise exceptions on other threads...), this is just one, but a very common pattern in WinForms.

I hope this solution will give you the idea, again feel free to ask any further questions....

Kind regards
Johannes
 
Share this answer
 
v2
Comments
AlwaysLearningNewStuff 26-Jan-15 8:00am    
Thank you so much! I need to learn a lot of new things so I will need time before I report my results. Hopefully I will manage to fix the problem using your code as a reference...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900