secondo me non è il finally, ma la chiusura della connessione che c'e' dentro.
Ti ripeto, l'SQLDataReader è un oggetto connesso, non in memoria come il Dataset 
Questo è il primo metodo che usavi, chiudevi sia il reader che la connessione.
Il finally viene eseguito sempre, è un problema di flusso e logica, l'errore che ottenevi infatti te lo diceva: "Invalid attempt to call FieldCount when reader is closed".
Inoltre non restituisci il reader nel punto giusto secondo me, andrebbe restituito alla fine...
codice:
public SqlDataReader ddlGruppi(int soluzione)
{
SqlDataReader reader = null;
try
{
SqlCommand cmd = new SqlCommand("select_gruppi_soluzione", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@soluzione#", soluzione);
cmd.Connection = conn;
conn.Open();
reader = cmd.ExecuteReader();
return reader;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
if (reader != null)
{
reader.Close();
}
conn.Close();
}
}