-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How can discard exception in async task correctly ? #92
Comments
The "InvalidOperationException" indicates there is a bug in the FlowBehavior-Handling for async methods. Async support was added by @keith-anders. This would have to be investigated. But can you explain the original use case as I think the usage of aspect here is not recommended? Also, using static variables from other classes in aspect looks like a code smell. If you apply your aspect multiple times to other methods you will just create a mess of dangling "CancellationTokenSources". Which CancellationTokenSource will then be canceled? Think about if you have multiple "TestViewModels". And creating all aspect again for each TestViewModel seems also not be correct. If you only want to suppress the "OperationCanceledException" then try using an extension method. class Program
{
static async Task Main(string[] args)
{
var model = new TestViewModel();
Func<Task> func = () => model.Run();
await func.SuppressCancel();
}
}
public class TestViewModel
{
private CancellationTokenSource _cts;
public async Task Run()
{
_cts = new CancellationTokenSource(3000); // cancel after some time for testing purpose
// simulate long tasks
for (var i = 0; i < 1000; i++)
await LongTask(i, _cts.Token); // task won't run in parallel. If this was the intention create all tasks and call Task.WaitAll()
}
public async Task LongTask(int i, CancellationToken cancellationToken)
{
Trace.WriteLine(i + " - work part 1");
await Task.Delay(500);
cancellationToken.ThrowIfCancellationRequested();
Trace.WriteLine(i + " - work part 2");
await Task.Delay(500);
cancellationToken.ThrowIfCancellationRequested();
Trace.WriteLine(i + " - work part 3");
await Task.Delay(500);
cancellationToken.ThrowIfCancellationRequested();
}
public void Stop()
{
Trace.WriteLine("Task will be cancel");
_cts.Cancel();
_cts = null;
}
}
public static class TaskExtensions
{
public static async Task SuppressCancel(this Func<Task> func)
{
try
{
var task = func();
await task;
}
catch (OperationCanceledException)
{
// suppress cancel
}
}
} |
Thank you for your wise advice,I will consider your advice very well, That is really universal practice currently. I think it is necessary for me to explain my trouble. I am develop about an automation system that consist of a lot of motion and can stop,play,pause,skip so on. Therefore, there is a lot of IO behavior and long time calculation in the system. Unfortunately most of the code was inherit form long ago and most do not support TAP pattern. If I pass a CancellationToken from the top level it means I must to rewrite a lot of code and CancellationToken will diffuse in the whole.That was a frustrating job. So I m looking for a clean and easier way to add feature . I want stick to principle about Separation of concerns, but there is easier cause chaos for TAP pattern. Maybe I understood it wrong. |
I want to simplify the process of cancel async task with MethodBoundaryAspect.
So, I write the code below:
and caller:
But he will throw a System.InvalidOperationException:“An attempt was made to transition a task to a final state when it had already completed.”
How can i discard OperationCanceledException correctly ?
The effect I expected is as below:
The text was updated successfully, but these errors were encountered: