This code here is not handling the Exception thrown, when it cant connect to the Server. Any Ideas why? Thanks!
public Form1()
{
InitializeComponent();
StartClient();
}
async private Task StartClient()
{
try
{
await ConnectToServerAsync();
}
catch (System.Net.Sockets.SocketException)
{
MesssageBox.Show("TEST");
}
}
private Task ConnectToServerAsync()
{
return Task.Factory.StartNew(() => client.Connect(host, port));
}
The thing is: "async void" is very dangerous construct that should almost never appear in your production code. Async method is not a list of statements internally, it's kind of state machine that switches from one "await" statement to another, doing various things in-between while "awaiting". So, once you got an exception raised inside that state machine, you need special context to preserve the stack trace etc. Void methods do not provide such a context. Return Task or Task<something> instead.
As a further reading, I could recommend Phil Haack's very nice blogpost: http://haacked.com/archive/2014/11/11/async-void-methods/
There are various problems with this code. First, using async void is only meant for event handlers. An async void method can't be awaited and any exceptions it throws can't be handled. Second, Task.Factory.StartNew(()=>client.Connect(host,port)) fakes asynchronous execution. It still blocks a thread. Asynchronous execution means that no thread is blocked while waiting for the operation to complete.
I assume you use TcpClient. This class already has a ConnectAsync method that connects in an asynchronous manner. You could simplify your code to this:
private async Task StartClient()
{
try
{
await client.ConnectAsync(host,port);
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString());
}
}
If you want to start the client in response to a UI event, eg a button click, you'd write :
async void Button1_Click(object sender, EventArgs e)
{
await StartClient();
}
or
async void Button1_Click(object sender, EventArgs e)
{
try
{
await StartClient();
//Work with the client
}
catch(Exception exc)
{
MessageBox.Show(exc.ToString());
}
}
Finally, use a logging library instead of MessageBox.Show, eg log4net so you don't lose exception messages due to threading issues.
Related
I have the following code in the
private void Button_Click(object sender, EventArgs e)
{
try
{
Task.Run(async () => await Presenter.Search());
}
catch (Exception ex)
{
LabelMessage.Text = "Error:....";
}
}
The function Presenter.Search() may get exceptions in some cases and I want to show an error message. However, the exception is not raised? I can only see it in the Visual studio debugger.
Really this should be written like so:
private async void Button_Click(object sender, EventArgs e)
{
try
{
await Presenter.Search();
}
catch (Exception ex)
{
LabelMessage.Text = "Error:....";
}
}
Now the call is awaited and the exception will be handled correctly. Note that you shouldn't typically use async void for the reasons listed here, but in the case of UI event handlers it's the recommended approach.
First of all, if Presenter.Search already returns a Task you should consider to make the event handler async and simply put
await Presenter.Search();
in the try-catch block.
The reason of Task.Run(Func<Task>) overload exists is that you can force an already existing Task to be scheduled for execution on a pool thread. This case can be justified in very rare cases as normally you should rely on the internal implementation of the Task returning methods. But if you know that an async method does not use threads (for example, just returns a Task, which will be completed on a specific event) and you are confident enough about forcing the execution on a pool thread you can do it this way. But also in this case you should await the external task; otherwise, the call is fire-and-forget and you will not catch anything:
await Task.Run(() => Presenter.Search());
Please note that I omitted the inner async-await:
await Task.Run(async () => await Presenter.Search());
This would also work and is functionally equivalent to the previous version but adds a needless inner state machine to the chain of tasks to execute.
TL;DR: Without knowing any further details await Presenter.Search(); seems to be the better solution but also await Task.Run(() => Presenter.Search()); can be justified if you know what you are doing.
The following code does not catch my OperationCancelException which is thrown by calling ct.ThrowIfCancellationRequested.
public partial class TitleWindow : Window, IAsyncInitialization
{
public Task Initialization{get; private set;}
CancellationTokenSource cts;
public TitleWindow()
{
InitializeComponent();
cts = new CancellationTokenSource();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
cts.Cancel();
Initialization = GetCancelExceptionAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation canceled!");
}
}
public async Task GetCancelExceptionAsync(CancellationToken ct)
{
await Task.Delay(1000);
ct.ThrowIfCancellationRequested();
}
}
However if i replace my Window_Loaded method with the following (making it async and await the call of my async method), the exception gets caught.
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
cts.Cancel();
await GetCancelExceptionAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation canceled!");
}
}
Why is my first approach not working? Is the exception not properly propagated to the correct synchronization context?
I was trying to use The Asynchronous Initialization Pattern described in Stephen Clearys blog post to be able to later on await a task which was started in a constructor (and in order to make it comparable to my second example I used the (async) Window_Loaded event to await methods there right away, like suggested to me in a previous question). Then I wanted to provide an option to cancel the async method that I started in the constructor, where i am currently stuck because the exception handling does not work as I expected.
With my "non-working" code, I can catch the exception by putting await Initialization in a try-catch block somewhere, but I still get an additional unhandled exception.
How do I implement this in a way that allows me to await my async method later on (to ensure that I do not work with an inconsistent state of my object) and still being able to cancel that long-running Task (which would of course need to return/set default values)?
In your first example the exception is not caught because it does not occure before leaving the try/catch block. If you want to catch it there you need to wait/await it there exactly like you do in the second example.
If you do not await the returned task the method continues execution and leaves the try/catch block before the exception actually occures...
If you want to catch the exception "out of band" you can also register to TaskScheduler.UnobservedTaskException (this event is called if a task is throwing an exception which is nowhere caught) to get all uncaught exceptions or monitor the tasks Exception property. May also check out THIS answer.
Exeption is thrown in the task on another thread.
public async Task GetCancelExceptionAsync(CancellationToken ct)
{
try
{
await Task.Delay(1000);
ct.ThrowIfCancellationRequested();
}
catch (Exception e)
{
// your Cancleation expeption
}
}
I have a strange problem combining the async/await to make it work:
I created a small procedure, which should handle basically the try/catch of every action:
internal static void HandledAction(Action action, Info infoBar)
{
try
{
action();
}
catch (Exception ex)
{
infoBar.SetError("An Exception occured: " + ex.Message);
WriteLog(ex.StackTrace);
}
Nohing to fancy, but it's worth since changing error-handling is very easy made.
But what happens, if I'd like to get Data async in the Lambda? Lets take this simple example:
private void mnuImportData_Click(object sender, RoutedEventArgs e)
{
ActionHelper.HandledAction(async () =>
{
throw new NotImplementedException("Ups");
}, infoMain);
}
Sure, the HandledAction gets called, passes, since it gets the pointer back, and the exception gets thrown, of course not handled.
I imagine I have to create a AsyncHandledAction, and set the action async, but is there a easier way to solve this problem?
I guess many people use a central exception-handling, and there are far better solutions for this?
Thanks in advance
Matthias
Edit: I created an example, which should shpw netter I need: I basically dont want the whole Action I pass being awaitable, but one call in the Lambda is:
ActionHelper.HandledActionAsync(() =>
{
//elided
CheckFileResult rslt = await excelImport.CheckFilesAsync(tmpPath);
//elided
}, infoMain);
Of course, by doing so, I get the error:
Error 3 The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
The reason is: Action instead of Func. Since yours:
async () =>
{
throw new NotImplementedException("Ups");
}
in fact is:
async void Method() { }
when Func<Task> is:
async Task Method() { }
Async void will capture SynchronizationContext.Current and when exception is thrown it will be posted to SynchronizationContext by SynchronizationContext.Post() - (in windows runtime you can catch these types of exception). In case of ASP.NET/Console application SynchronizationContext.Current returns null which means that exception would be propagated to Thread Pool and I'm not sure but I think it is not possible to catch it. However when there is returned Task by asynchronous method exception could be marshaled to the caller through this returned Task. It is also worth mention that async lambda expresions will always prefer methods with Func<Task> over Action. General rule is: never use async void (async Action) unless it is "top-level method" (in example event handler).
You need an async version of HandleAction
internal static async Task HandledAction(Func<Task> action, Info infoBar)
{
try
{
await action();
}
catch (Exception ex)
{
infoBar.SetError("An Exception occured: " + ex.Message);
WriteLog(ex.StackTrace);
}
}
of course you should call the method with await
private async void mnuImportData_Click(object sender, RoutedEventArgs e)
{
await ActionHelper.HandledAction(async () =>
{
throw new NotImplementedException("Ups");
}, infoMain);
}
I've tried to read up on async methods and am now trying to create my own async method. The method is a webservice call that returns a list of error logs. I'm not sure that I've understood correctly so I thought I'd share my code to see if I should do anything different.
All I want the code to do is return a list of errorlogs by calling a method GetAllErrorLogs(), that is a synchronized method. Since it can take a second to fetch all the error logs I want to have the opportunity to do other stuff once I called the GetAllErrorLogs() method. Here is the code.
[WebMethod]
public async Task<List<ErrorLog>> GetAllErrorLogs()
{
List<ErrorLog> errorLogs = new List<ErrorLog>();
await System.Threading.Tasks.Task.Run(() => {
errorLogs = ErrorLogRepository.GetAllErrorLogs();
});
if (errorLogs == null)
return new List<ErrorLog>();
return errorLogs;
}
Thanks!
I recently gave a talk at ThatConference on async on the server side, and I address this issue in the slides.
On the server side, you want to avoid the use of Task.Run and other constructs that queue work to the thread pool. As much as possible, keep thread pool threads available for handling requests.
So, ideally your repository would have an asynchronous method GetAllErrorLogsAsync, which would itself be asynchronous. If GetAllErrorLogs cannot be asynchronous, then you may as well just call it directly (removing the await Task.Run).
Since it can take a second to fetch all the error logs I want to have the opportunity to do other stuff once I called the GetAllErrorLogs() method.
If you have a GetAllErrorLogsAsync available, then this can easily be done using Task.WhenAll. However, if GetAllErrorLogs is synchronous, then you can only do this by doing parallel work in your request (e.g., multiple calls to Task.Run followed by Task.WhenAll).
Parallel code on the server must be approached with great trepidation. It is only acceptable in a very limited set of scenarios. The entire point of async on the server side is to use fewer threads per request, and when you start parallelizing, you're doing the opposite: multiple threads per request. This is only appropriate if you know your user base is very small; otherwise, you'll kill your server scalability.
I found this great codeproject detailed article about how to achieve that
http://www.codeproject.com/Articles/600926/Asynchronous-web-services-call-in-ASP-NET
**This is potentially wrong, read comments or spinoff question at HttpContext.Current after an await
If ErrorLogRepository.GetAllErrorLogs() is not thread-safe, it will cause weird bugs and potentially exception out. Make sure your code is ready for multi-threaded operation before switching to async methods, this is obviously very trivial advice but often overlooked. For example, if you reference HttpContext.Current in your methods, your code will die in the async method, and sometimes even AFTER the await. The reason is that the code within the async block will potentially be run on a separate thread, which will not have access to the same HttpContext.Current thread-static property, and await gets compiled into two methods. All code before an await gets run on one thread, and then calls the code after an await keyword as a continuation, but potentially on yet another thread. So sometimes your code will even work in an async block, only to choke unexpectedly after it gets "out" of the async back to what you think is a synchronous part of your code (but in reality everything after an await keyword is already not guaranteed to be the original thread).
Here is some production code...
using System.Web.Http;
using AysncTask = System.Threading.Tasks.Task;
public class myController : ApiControllerBase
{
[HttpPut]
[Route("api/cleardata/{id}/{requestId}/")]
public async AysncTask ClearData(Guid id, Guid requestId)
{
try
{
await AysncTask.Run(() => DoClearData(id, requestId));
}
catch (Exception ex)
{
throw new Exception("Exception in myController.ClearData", ex);
}
}
}
Handling Async exceptions is also VERY VERY important.. although this is for a windows console app, the same principles should apply.
source: https://blogs.msdn.microsoft.com/ptorr/2014/12/10/async-exceptions-in-c/
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncAndExceptions
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += (s, e) => Log("*** Crash! ***", "UnhandledException");
TaskScheduler.UnobservedTaskException += (s, e) => Log("*** Crash! ***", "UnobservedTaskException");
RunTests();
// Let async tasks complete...
Thread.Sleep(500);
GC.Collect(3, GCCollectionMode.Forced, true);
}
private static async Task RunTests()
{
try
{
// crash
// _1_VoidNoWait();
// crash
// _2_AsyncVoidAwait();
// OK
// _3_AsyncVoidAwaitWithTry();
// crash - no await
// _4_TaskNoWait();
// crash - no await
// _5_TaskAwait();
// OK
// await _4_TaskNoWait();
// OK
// await _5_TaskAwait();
}
catch (Exception ex) { Log("Exception handled OK"); }
// crash - no try
// await _4_TaskNoWait();
// crash - no try
// await _5_TaskAwait();
}
// Unsafe
static void _1_VoidNoWait()
{
ThrowAsync();
}
// Unsafe
static async void _2_AsyncVoidAwait()
{
await ThrowAsync();
}
// Safe
static async void _3_AsyncVoidAwaitWithTry()
{
try { await ThrowAsync(); }
catch (Exception ex) { Log("Exception handled OK"); }
}
// Safe only if caller uses await (or Result) inside a try
static Task _4_TaskNoWait()
{
return ThrowAsync();
}
// Safe only if caller uses await (or Result) inside a try
static async Task _5_TaskAwait()
{
await ThrowAsync();
}
// Helper that sets an exception asnychronously
static Task ThrowAsync()
{
TaskCompletionSource tcs = new TaskCompletionSource();
ThreadPool.QueueUserWorkItem(_ => tcs.SetException(new Exception("ThrowAsync")));
return tcs.Task;
}
internal static void Log(string message, [CallerMemberName] string caller = "")
{
Console.WriteLine("{0}: {1}", caller, message);
}
}
}
Under what scenarios would one want to use
public async Task AsyncMethod(int num)
instead of
public async void AsyncMethod(int num)
The only scenario that I can think of is if you need the task to be able to track its progress.
Additionally, in the following method, are the async and await keywords unnecessary?
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
Normally, you would want to return a Task. The main exception should be when you need to have a void return type (for events). If there's no reason to disallow having the caller await your task, why disallow it?
async methods that return void are special in another aspect: they represent top-level async operations, and have additional rules that come into play when your task returns an exception. The easiest way is to show the difference is with an example:
static async void f()
{
await h();
}
static async Task g()
{
await h();
}
static async Task h()
{
throw new NotImplementedException();
}
private void button1_Click(object sender, EventArgs e)
{
f();
}
private void button2_Click(object sender, EventArgs e)
{
g();
}
private void button3_Click(object sender, EventArgs e)
{
GC.Collect();
}
f's exception is always "observed". An exception that leaves a top-level asynchronous method is simply treated like any other unhandled exception. g's exception is never observed. When the garbage collector comes to clean up the task, it sees that the task resulted in an exception, and nobody handled the exception. When that happens, the TaskScheduler.UnobservedTaskException handler runs. You should never let this happen. To use your example,
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
Yes, use async and await here, they make sure your method still works correctly if an exception is thrown.
For more information see: https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
I have come across this very useful article about async and void written by Jérôme Laban:
https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.html
The bottom line is that an async+void can crash the system and usually should be used only on the UI side event handlers.
The reason behind this is the Synchronization Context used by the
AsyncVoidMethodBuilder, being none in this example. When there is no
ambient Synchronization Context, any exception that is unhandled by
the body of an async void method is rethrown on the ThreadPool. While
there is seemingly no other logical place where that kind of unhandled
exception could be thrown, the unfortunate effect is that the process
is being terminated, because unhandled exceptions on the ThreadPool
effectively terminate the process since .NET 2.0. You may intercept
all unhandled exception using the AppDomain.UnhandledException event,
but there is no way to recover the process from this event.
When writing UI event handlers, async void methods are somehow
painless because exceptions are treated the same way found in
non-async methods; they are thrown on the Dispatcher. There is a
possibility to recover from such exceptions, with is more than correct
for most cases. Outside of UI event handlers however, async void
methods are somehow dangerous to use and may not that easy to find.
The problem with calling async void is that
you don’t even get the task back. You have no way of knowing when the function’s task has completed. —— Crash course in async and await | The Old New Thing
Here are the three ways to call an async function:
async Task<T> SomethingAsync() { ... return t; }
async Task SomethingAsync() { ... }
async void SomethingAsync() { ... }
In all the cases, the function is transformed into a chain of tasks. The difference is what the function returns.
In the first case, the function returns a task that eventually produces the t.
In the second case, the function returns a task which has no product, but you can
still await on it to know when it has run to completion.
The third case is the nasty one. The third case is like the second case, except
that you don't even get the task back. You have no way of knowing when
the function's task has completed.
The async void case is a "fire and
forget": You start the task chain, but you don't care about when it's
finished. When the function returns, all you know is that everything
up to the first await has executed. Everything after the first await
will run at some unspecified point in the future that you have no
access to.
I think you can use async void for kicking off background operations as well, so long as you're careful to catch exceptions. Thoughts?
class Program {
static bool isFinished = false;
static void Main(string[] args) {
// Kick off the background operation and don't care about when it completes
BackgroundWork();
Console.WriteLine("Press enter when you're ready to stop the background operation.");
Console.ReadLine();
isFinished = true;
}
// Using async void to kickoff a background operation that nobody wants to be notified about when it completes.
static async void BackgroundWork() {
// It's important to catch exceptions so we don't crash the appliation.
try {
// This operation will end after ten interations or when the app closes. Whichever happens first.
for (var count = 1; count <= 10 && !isFinished; count++) {
await Task.Delay(1000);
Console.WriteLine($"{count} seconds of work elapsed.");
}
Console.WriteLine("Background operation came to an end.");
} catch (Exception x) {
Console.WriteLine("Caught exception:");
Console.WriteLine(x.ToString());
}
}
}
A brief explanation:
async Task<T> method() await can be used to wait till the execution is completed and it will return value of type T
async Task method() await can be used to wait till the execution is completed but no data is returned
async void method() can't be awaited and no data is returned [Example: async event execution]
My answer is simple
you can not await void method
Error CS4008 Cannot await 'void' TestAsync e:\test\TestAsync\TestAsyncProgram.cs
So if the method is async, it is better to be awaitable, because you can lose the advantage ofasync.