0

I've got method which I want to run asynchronously:

public async Task Send(MemoryMapModel memoryMap, SerialPort serialPort, ProgressBar progressBar, Settings settings)
{
    SendFrames(memoryMap, serialPort, progressBar, _token.Token, settings);
}

And I use it like this by Task.Run():

await Task.Run(async () => await _rtuLogic.Send(memoryMap, serialPort, pbProgressBar, settings).ConfigureAwait(false));

Method "Send" throws exceptions which I want to catch, but to do that, it has to be async Task, but there are no awaitable methods and VS wants me not to use async keyword.

Why can't I catch exceptions from Task.Run(() => void) but it do works for Task.Run(async () => async Task), though there are no awaitable methods?

EDIT: Also when I tried

Task.Factory.StartNew(() => { _rtuLogic.SendAsync(memoryMap, serialPort, pbProgressBar, settings); });

I can't catch and handle exceptions. If I don't use Task.Run(...) Send doesn't run asynchronously and freezes GUI.

  • 1
    why do you need `await Task.Run(async () => await ...)`? why don't you just `await _rtuLogic.Send(..)`? – vasily.sib Mar 18 '19 at 07:57
  • Possible duplicate of [What is the best way to catch exception in Task?](https://stackoverflow.com/questions/12980712/what-is-the-best-way-to-catch-exception-in-task) – Sinatr Mar 18 '19 at 07:59
  • `await _rtuLogic.Send(..)` doesn't make the code run asynchronously. It freezes GUI. – mzabialowicz Mar 18 '19 at 08:13
  • `var task = Task.Factory.StartNew(() => { /* action */ });` is almost the same as `Task.Run(...)` – mzabialowicz Mar 18 '19 at 08:14
  • I don't think your method needs to be `async`, but if you call it using `Task.Run()`, you do need to `await` it in order to get the exceptions it might throw. – HHLV Mar 18 '19 at 08:25
  • Where are you calling this from? `await Task.Run(...)` should be correct and not block. Alternatively try the continuation style: `Task.Run(...).ContinueWith(t => ...)` – Dennis Kuypers Mar 18 '19 at 08:28
  • But when i do not use `async Task Send(...)` I can't catch and handle exceptions. – mzabialowicz Mar 18 '19 at 08:32
  • That is not true. Roughly a method that does `DoA();await SomeAsync();DoB()` translates to `DoA();await SomeAsync().ContinueWith(_ => DoB())`. See [MSDN](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.continuewith#System_Threading_Tasks_Task_ContinueWith_System_Action_System_Threading_Tasks_Task__) You get the task passed into your callback and can do t.Exception to see the exception.` – Dennis Kuypers Mar 18 '19 at 08:36
  • I'm calling it from GUI. It's button click event. – mzabialowicz Mar 18 '19 at 08:36
  • You can't use SendFrames to achieve what you want, it is straight up broken. You need to rewrite it. The problem with it is, that is has 2 concerns that directly conflict under your requirements. SendFrames updates the UI and it does I/O bound operations on the same thread. – Aron Mar 18 '19 at 08:38
  • This is the class of problem that async await was designed specifically to deal with. – Aron Mar 18 '19 at 08:40

1 Answers1

1

Some people may see it as a bit outdated now we have async, but you seem to be throwing async/await in everywhere and hoping it'll solve your problem.1

So I'd suggest ditching this attempt and look at using BackgroundWorker instead. It lets you clearly separate the bits that should happen "elsewhere" from the bits that still need to access the UI and should help avoid blocking it.

Task.Run should generally be avoided unless you have CPU bound work that you want to move off the current thread.

If you do want to go async/await then ideally you find the async variant of SendFrames and use that instead. But if that's not available/written yet then don't try to pretend that it's async.


1A now deleted answer linked to this answer by Stephen Cleary which in turn links off to other articles/posts about async, which I'd suggest you should try to ready all of them and other Stephen Cleary blog posts too (There is no thread should always be a recommended read)

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448