Rzucanie wyjątków w Taskach

0

Dlaczego throw new Exception() w poniższym kodzie nie jest wychwytywany przez istniejący try catch i co zrobić żeby był?

        public static async Task<List<Client>> GetClientsAsync(string resellerLoging, string resellerPassword, int sessionTimeout)
        {
            try
            {
                return await Task.Run(() =>
                {
                    throw new Exception();
                    .// some code
                    return clients;
                });
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
0

Bo użyty przez Ciebie blok try{} catch(){} obejmuje operację utworzenia zadania (Task) i zwrócenia go, a kod zawarty w zadaniu nie jest wykonywany od razu.

Może ten przykład Ci to lepiej wyjaśni. Ta funkcja zwraca obiekt typu Client. My zwracamy nulla i nie ma w tym nic złego, nie wystąpi żaden wyjątek. Dopiero w kodzie używającym tej funkcji jak użyjesz jakiegoś pola tego obiektu to rzuci wyjątek, że Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu czy jakoś tak.

public static Client GetClients(string resellerLoging)
        {
            try
            {
                return null;                
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

Jeżeli chcesz przechwycić ten wyjątek to zrób przechwytywanie w funkcji Run()

return await Task.Run(() =>
                {
                    try
                    {
                        //code                        
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }
                });
0

Ok, a czy istnieje możliwość napisania tego w ten sposób, żeby ten wyjątek w jakiś sposób propagował w górę do tego bloku try catch, który wskazałem? Jeżeli zrobię tak jak pokazałeś z blokiem try catch wewnątrz Taska to mogę ten wyjątek obsłużyć, ale jeżeli chcę go rzucić, żeby propagował dalej to znowu pojawia się błąd Unhandeled exception. Chciałbym generalnie mieć obsługę wyjątków w tych nadrzędnych metodach, żeby w jednym miejscu móc łatwo wypisywać błędy dla użytkownika.

0

Chodzi o takie coś?

        public static async Task<List<Client>> GetClientsAsync(string resellerLoging, string resellerPassword, int sessionTimeout)
        {
            Task<List<Client>> task = new Task<List<Client>>(() =>
            {
                //code
                throw new Exception();
            });
            try
            {
                task.Start();
                task.Wait();                
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);//czy logger, czy cokolwiek
            }
            return task.Result; //tutaj mozna przekazac Exception do kodu wywolujacego
        }

Ewentualnie do poczytania: https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/exception-handling-task-parallel-library

0

W dalszym ciągu w takim kodzie mam:
Exception User-Unhandled
System.Exception: 'Zgłoszono wyjątek typu 'System.Exception'.'

0

W zasadzie wyszło, że to co chcę uzyskać powinno wyglądać tak:

        public static async Task<List<Client>> GetClientsAsync(string resellerLoging, string resellerPassword, int sessionTimeout)
        {
            try
            {
                return await Task.Run(() =>
                {
                    throw new Exception();
                    .// some code
                    return clients;
                });
            }
            catch (AggregateException ex)
            {
                throw new Exception(ex.InnerException.Message);
            }
        }

Wtedy jeżeli kod odpali się w Relese to przy rzuceniu wyjątku informacja o błędzie zostanie przekazana do nadrzędnej metody, błąd się ładnie wyświetli, a program nie pójdzie w maliny. Pytanie tylko dlaczego w trybie Debug wyskakuje mi:
Exception User-Unhandled
System.Exception: 'Zgłoszono wyjątek typu 'System.Exception'.'
Po co to w ogóle się pokazuje, skoro wszytko działa dobrze?

0

No to jak chcesz przechwytywać w jednym miejscu to przechwytuj tam gdzie wywołujesz tą metodę

try
            {
                await GetClientsAsync("", "", 1);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Wyjątek");
            }

Tylko tak, jak będziesz debugował kod to wychwyci Ci ten wyjątek w funkcji Run i będziesz musiał w Visualu kliknąć Continue i wtedy będzie go propagował do tego bloku gdzie jest wywołanie GetClientsAsync. Pewnie da się to gdzieś ustawić, w sensie żeby nie wstrzymywał działania programu, żeby robił to od razu, ale na tą chwilę nie wiem jak. W Visualu jest coś takiego jak Exception Setting i tam idzie ustawiać przy jakich wyjątkach ma wstrzymywać działanie nawet jak są przechwytywane, więc pewnie tam gdzies to trzeba ustawić. Jeżeli uruchomisz program StartWithoutDebuging to program będzie działał normalnie.

0

Jak nie chcesz, żeby wyświetlało Ci ten pierwszy wyjątek to w Visualu: Tools > Options > Debugging > General > odznaczasz Enable Just My Code

1 użytkowników online, w tym zalogowanych: 0, gości: 1