1

This is a small routine( i have written line numbers so it will be easier to make reference) I have for transferring data from my desktop application to my mobile device. It is working perfectly but I am unable to handle the exceptions properly. if i write my code as it is below the System.Net.Sockets.SocketException exception is handled but since client fails to connect thats why the next line(17) produces an exception

System.InvalidOperationException: 'The operation is not allowed on non-connected sockets.

Now if i try to put line 17 and 18 in try then another error arises that stream becomes a local object and due to which line 24 produces error.

If i declare stream in the beginning then another error occurs on line 24

ERROR :use of unassigned variable stream.

its sort of a deadlock for me i am unable to work my way through it. Thanks in Advance!!

 C#

1 void  BluetoothClientConnectCallback(IAsyncResult result)
2        {
3                BluetoothClient client = (BluetoothClient)result.AsyncState;
4                Stream stream;
5
6                try
7                {
8                    client.EndConnect(result);
9                }
10
11                catch (System.Net.Sockets.SocketException)
12                {
13                   MessageBox.Show("Unable to connect to device!", "Error", 
                     MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
14                    
15                }
16
17                stream = client.GetStream();
18                stream.ReadTimeout = 1000;
19                  while (true)
20                  {
21                      while (!ready) ;
23                      message = Encoding.ASCII.GetBytes("{");
24                      stream.Write(message, 0, 1);
25                      ready = false;
26   
27                  } 

  • 1
    a bit confused, your connection fails but you still want to be able to run code against the stream it returns? Or you just want to know how to use try/catch correctly so the rest of the code does not execute on failed connection? – JohnChris Jun 21 '19 at 07:26
  • if the client is not connected, you cannot use `client.GetStream();` one solution is to put the lines which are dependent on the connection within the try block. – Sebastian Siemens Jun 21 '19 at 07:26
  • I dont want my application to crash thats why I dont want those lines to execute if it fails to connect – Muhammad Sufyan Raza Jun 21 '19 at 07:28
  • Sebastian I tried it but then it produces an error on line 24 ERROR :use of unassigned variable stream. – Muhammad Sufyan Raza Jun 21 '19 at 07:29
  • 1
    @MuhammadSufyanRaza updated answer with an important thing about streams and `using` – JohnChris Jun 21 '19 at 07:39

2 Answers2

3

Ok so your issue is try/catch is not covering the correct scope, should be like this:

void BluetoothClientConnectCallback(IAsyncResult result)
{       
    try
    {
        BluetoothClient client = (BluetoothClient)result.AsyncState;
        Stream stream;

        client.EndConnect(result);


        stream = client.GetStream();
        stream.ReadTimeout = 1000;
        while (true)
        {
            while (!ready) ;
            message = Encoding.ASCII.GetBytes("{");
            stream.Write(message, 0, 1);
            ready = false;

        }
    }

    catch (System.Net.Sockets.SocketException e)
    {
        MessageBox.Show($"Unable to connect to device with message:\r\n{e.Message}", "Error",
                   MessageBoxButtons.OKCancel, MessageBoxIcon.Error);

    }
    catch (Exception ex)
    {
        //general exception catch, handle or ignore, but best is to log
    }
}

If you want to "hide" the error then you need to have an empty catch but that is never recommended

Probably some reading on try/catch is needed, check out here

Also worth mentioning, when using Streams best practise is to use using as to ensure it is disposed correctly and not cause a memory leak, e.g:

void BluetoothClientConnectCallback(IAsyncResult result)
{
    try
    {
        BluetoothClient client = (BluetoothClient)result.AsyncState;    
        client.EndConnect(result);
        using (var stream = client.GetStream())
        {
            stream.ReadTimeout = 1000;
            while (true)
            {
                while (!ready) ;
                message = Encoding.ASCII.GetBytes("{");
                stream.Write(message, 0, 1);
                ready = false;
            }
        }
    }

    catch (System.Net.Sockets.SocketException e)
    {
        MessageBox.Show($"Unable to connect to device with message:\r\n{e.Message}", "Error",
                   MessageBoxButtons.OKCancel, MessageBoxIcon.Error);    
    }
    catch (Exception ex)
    {
        //general exception catch, handle or ignore, but best is to log
    }
}

Also some tips about handling exception from another SO post here

JohnChris
  • 1,360
  • 15
  • 29
  • 2
    `catch (System.Net.Sockets.SocketException e) { MessageBox.Show($"Unable to connect to device with message:\r\n{e.Message}",...` - let user know what exactrly happened. – Dmitry Bychenko Jun 21 '19 at 07:55
1

Execute everything that could throw exceptions inside the try block and catch any exception which you think you should handle.

void BluetoothClientConnectCallback(IAsyncResult result)
{
  BluetoothClient client = (BluetoothClient)result.AsyncState;
  Stream stream;

  try
  {
    client.EndConnect(result);
    stream = client.GetStream();
    stream.ReadTimeout = 1000;
    while (true)
    {
      while (!ready) ;
      message = Encoding.ASCII.GetBytes("{");
      stream.Write(message, 0, 1);
      ready = false;
    }
  }

  catch (System.Net.Sockets.SocketException)
  {
    MessageBox.Show("Unable to connect to device!", "Error",
    MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
  }
  catch (InvalidOperationException ex) 
  { 
     MessageBox.Show("Invalid operation exception!", "Error",
     MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
  }
  catch (Exception ex) 
  {
     MessageBox.Show("Exception thrown!", "Error",
     MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
  }
}