-2

I have a windows service which runs a number of async tasks, however I'm having a problem with catching exceptions and returning them back to the calling method. In the following psuedo-code example, the try/catch is simply stopping the entire service rather than running up the stack. What's the best way to implement a Try/Catch in an async task?

foreach (var t in tables)
{
    try
    {
        new Task(async () =>
            {
                try
                {
                    //Do stuff
                }
                catch (DataError e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
        };
    }
    catch (Exception e)
    {
        return new DatabaseActionResult();
    }
}

Ultimately, I want to catch and return a DatabaseActionResult object no matter what happens in any task. Again though, once the throw e happens, it totally shuts down the service and none of the other Try/Catch blocks catch anything.

How can I get this working without "awaiting" the task?

Nick Posey
  • 109
  • 3
  • 9
  • `new Task()` cannot throw. You need to handle failed tasks, probably by `await Task.WhenAll(tables.Select(t => Task.Run(...)))` – SLaks Nov 14 '17 at 23:07
  • 1
    Don't use the task constructor *ever*. If you have an `async` method, then don't wrap that async method in a task constructor. The `async` method *Already* returns a `Task`. – Servy Nov 14 '17 at 23:29
  • 1
    @SLaks There's no need to use `Task.Run` to wrap an `async` method either. Just call the `async` method and you're done. – Servy Nov 14 '17 at 23:30
  • I can't use await because I need it to run 4 tasks at a time until all "n" tasks have completed, but if any one of them fail, then I want to break out and return the failure to the calling method (and ideally cancel all other remaining tasks that were called in that same method). What do you think would be the best way to do that? – Nick Posey Nov 14 '17 at 23:31
  • @NickPosey Search Google. There are lots and lots of examples of people doing that kind of stuff. – Servy Nov 14 '17 at 23:35
  • Please forgive my newness to async tasks, but how could I execute the same command without wrapping it in a Task? When I remove new Task(async () => and just leave "new () => async void() =>" or even "new async Action(() =>" the IDE tells me that it can't resolve async. I'm trying to do this inline if at all possible. – Nick Posey Nov 14 '17 at 23:38
  • @Servy I've been searching Google for a solution to this problem all day long in addition to asking questions on StackOverflow. Just haven't found a solution yet that has actually worked the way I'm trying to get it to work. :( – Nick Posey Nov 14 '17 at 23:44
  • @NickPosey Have you done anything with Task.WhenAll? I set up a test to run this but I'm not sure it actually solves your problem. https://dotnetfiddle.net/Ar30wH – thinklarge Nov 15 '17 at 00:22
  • _"of the other Try/Catch blocks catch anything"_ -- you've only got one other. And it doesn't catch the exception because a) you never start the `Task` you created, and b) even if you had, you don't observe the task result inside that try/catch block, and so there's no exception for that block to catch – Peter Duniho Nov 15 '17 at 01:04
  • @NickPosey: It depends on whether you're doing non-blocking or CPU-bound work. You want either existing `*Async()` methods or `Task.Run()`, respectively, then use `await Task.WhenAll()`. Read http://blog.slaks.net/2014-12-23/parallelism-async-threading-explained/ – SLaks Nov 15 '17 at 04:02

1 Answers1

-3

It seems to me that async is intended to be used with await for error catching by design. I don't see a good way to do what you're trying to do.

If you want more control over the way the errors are handled without having to await the task, you could maybe run the task in a separate thread explicitly, rather than letting async handle it.

boxcartenant
  • 271
  • 2
  • 14