3

INTRODUCTION AND RELEVANT INFORMATION:

I am an inexperienced C# developer that inherited colleague's project 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:

// 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:

// 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.

Community
  • 1
  • 1
AlwaysLearningNewStuff
  • 2,939
  • 3
  • 31
  • 84
  • 1
    you can have multiple catch blocks. So try{}catch(SocketException){//handle socket errors}catch(Exception){\\handle other errors} – Tsef Jan 22 '15 at 11:44
  • @zaf: I might be wrong, but after searching online, I have found out that `m_ftp.BeginConnect(username, password);` call launches separate thread. It is exactly in this thread that exception occurs. Modifying code per your instructions didn't change a thing, sadly. It seems that after removing `try/catch` blocks, exception bubbles up in the thread, never reaching my form, thus terminating the app. Again, I might be wrong, I am very inexperienced but this is my logic... – AlwaysLearningNewStuff Jan 22 '15 at 11:58
  • Sorry I missed the BeginXXX part. Anyways, I'm not familiar with the library you're using but usually .net async method which use the BeginXXX have an async callback parameter. In this callback you can try&catch errors. Try and see if there's an overload for the BeginConnect method you're using. To "bubble" up the exception to the UI thread you can use a SynchronizationContext. – Tsef Jan 22 '15 at 12:17
  • @zaf: *I'm not familiar with the library you're using* Neither am I, it was used by the colleague from whom I inherited the project :) *usually .net async method which use the BeginXXX have an async callback parameter. In this callback you can try&catch errors. Try and see if there's an overload for the BeginConnect method you're using. To "bubble" up the exception to the UI thread you can use a SynchronizationContext.* A lot of useful info to process at the moment, I will search online and see what will happen. Thank you for pointing me in the right direction. – AlwaysLearningNewStuff Jan 22 '15 at 12:26

1 Answers1

0

Async-style methods (e.g. BeginXxx) can only report errors in the callback/event because errors occur only after the call has returned. Handle the error in the callback. It will be thrown by the EndXxx method.

For every BeginXxx call there must be a corresponding EndXxx call, typically made in the callback.

This is the APM pattern.

usr
  • 168,620
  • 35
  • 240
  • 369
  • Thank you for answering, I highly appreciate it. Being new to all this, it might take time for me to implement your solution before I officially accept your answer so please be patient. Best regards. – AlwaysLearningNewStuff Jan 22 '15 at 12:40
  • If you want a simpler model, use await if your library supports it. That's by far the easiest way to run async work in combination with a UI. Without await don't use async IO. Start a task using Task.Run that does all the work. No need for events or callbacks anymore. – usr Jan 22 '15 at 12:46