How to hit the breakpoint at catch block when working with TPL - parallel-processing

As I started understanding thru the TPL. I got stuck over in this code. I have 2 task. Task1 thows ArgumentOutOfRangeException and Task2 throws NullReferenceException.
Consider this below code:
static void Main(string[] args) {
// create the cancellation token source and the token
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
// create a task that waits on the cancellation token
Task task1 = new Task(() => {
// wait forever or until the token is cancelled
token.WaitHandle.WaitOne(-1);
// throw an exception to acknowledge the cancellation
throw new OperationCanceledException(token);
}, token);
// create a task that throws an exceptiono
Task task2 = new Task(() => {
throw new NullReferenceException();
});
// start the tasks
task1.Start(); task2.Start();
// cancel the token
tokenSource.Cancel();
// wait on the tasks and catch any exceptions
try {
Task.WaitAll(task1, task2);
} catch (AggregateException ex) {
// iterate through the inner exceptions using
// the handle method
ex.Handle((inner) => {
if (inner is OperationCanceledException) {
// ...handle task cancellation...
return true;
} else {
// this is an exception we don't know how
// to handle, so return false
return false;
}
});
}
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
I have put the try catch block for Task.WaitAll(task1, task2). It should ideally hit the breakpoint in ex.handler statement inside Catch block. As I understand that whatever may be the result it should hit the catch block.
Same case is happening if I have task1.Result/task2.Result.
My Question is: In debug mode why isn't the breakpoint being hit at the catch block when I am intentionally throwing it from task as I want to examine the statements under catch block. It just puts yellow mark at saying "NullReferenceException unhandled by the user code".
Task task2 = new Task(() => {
throw new NullReferenceException();
});
How do I hit the break point at catch block???
Thanks for replying :)

As Arne Claassen explained in their comment, the debugger pauses execution at the point the original exception is thrown because the thread does not handle the exception. If you continue exceution (F5 or play button), the program should continue to the point where you are handling the exception in your continuation.

Related

How to handle InterruptException on Future#get()?

public void produceMessage(String dataPushNotif) {
PushNotif msg = PushNotif.newBuilder()
.setDatapushnotif(dataPushNotif)
.build();
ListenableFuture<SendResult<String, PushNotif>> future =
kafkaTemplate.send(destTopic, msg);
try {
var result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
log.debug(buildSuccesLogMessage(result));
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
log.debug("FAILED: {}", e);
}
}
With the code above I'm getting a sonarlint warning of Either re-interrupt this method or rethrow the "InterruptedException" that can be caught here. (java:S2142)
I could handle success and failure to send gracefully with addCallback(), but I don't see any other way to set a timeout on the thread execution.
Is there any way to handle the sonarlint warning? Or handle the future gracefully with a timeout option?
Don't use multi-catch and call Thread.currentThread().interrupt() in the InterruptedException catch block so that the next interruptible operation will get the exception.
It is bad practice to "swallow" interrupts.

Kotlin Coroutines remove exception handler from scope

In code below I am fetching some data. If error/exception was thrown I want the exception handler to catch it. Once done with fetching, I am posting the result using LiveData to whoever is observing.
What I am trying to achieve is that the exception handler to finish its job once I post the result. Which means, if the observer handling the result also throws an exception, I don't want the coroutine exception handler to catch it (Which is the case in code below).
fun loadPrerequisites(resultObserver: MutableLiveData<PrerequisiteDataHolder?>) {
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
resultObserver.postValue(null)
}
scope.launch(Dispatchers.IO + exceptionHandler) {
val deferredCreationScheme = async {
fetchCreationScheme()
}
val creationScheme = deferredCreationScheme.await()
//TODO remove exception handler at this stage?
resultObserver.postValue(PrerequisiteDataHolder(creationScheme))
}
}
Is there a way to remove the exception handler before posting the result to the LiveData? Or must I introduce a new scope?
You seem to have misunderstood the purpose of the coroutine exception handler. It is the coroutine equivalent of uncaughtExceptionExceptionHandler in Java and its purpose is to inform you of an exception that has already broken its coroutine. You seem to want to use it to implement business logic-level exception handling.
The coroutine exception handler is not a replacement for the try-catch block, and the latter is what you should use in your case.
I think you don't need async in your code in the first place, I believe this is all you really need:
scope.launch(Dispatchers.IO) {
resultObserver.postValue(
try {
PrerequisiteDataHolder(fetchCreationScheme())
} catch (e: Exception) {
null
}
)
}
I typically use a helper function for code like this:
inline fun <T> tryOrNull(block: () -> T) = try {
block()
} catch (t: Throwable) {
null
}
Then your code becomes
scope.launch(Dispatchers.IO) {
tryOrNull { PrerequisiteDataHolder(fetchCreationScheme()) }
.also { resultObserver.postValue(it) }
}

how to make TCP server in xamarin that does not freeze my app

I have a TCP Server with an start method looking like :
public async Task Start()
{
using (Canceler.Token.Register(() => listener.Stop()))
{
try
{
listener.Start();
var tcpClient = await listener.AcceptTcpClientAsync();
var clientStream = tcpClient.GetStream();
while(!CloseAll)
{
while (!clientStream.DataAvailable)
{
if (CloseAll)
{
break;
}
}
Byte[] bytes = new Byte[tcpClient.Available];
clientStream.Read(bytes, 0, bytes.Length);
String data = Encoding.UTF8.GetString(bytes);
Debug(data);
}
}
catch (Exception exc)
{
Debug(exc.Message);
Canceler.Token.ThrowIfCancellationRequested();
throw;
}
}
}
And then the communication class that handles it goes like:
internal async void Init()
{
DebugMessage("initializing gameBrain");
TCP = new TCPController();
TCP.newDebugMessage += Debug;
await TCP.Start();
}
And at the topmost, in the page we have :
public MainPage(GameBrain _brain)
{
InitializeComponent();
Brain = _brain;
Brain.newMessageToUI += NewMessageFromBrain;
Brain.Init();
}
I ran the thing and it works at the beginning. The UI is responsive (I added a button with a displayAlert for testing)
I noticed that the system freezes after the TCP client connects. In the inner while of the Start but ... I thought it was expected!
I thought the Start will run in a different thread while the app get's freed of it. To be honest I was used to backgroundworkers but I'm moving from there to Tasks, and there is clearly somethign I don't get.
How should that be done ?
In C#, async and await are used to allow code to keep executing while some asynchronous process is being done. This does not at all mean that you are starting a parallel process on another thread.
When you call this:
internal async void Init()
{
(..)
await TCP.Start();
}
You are merely saying to the runtime that TCP.Start() will eventually have a point in the execution where some asynchronous process (like an HTTP request to a 3rd party) is started and that it is allowed to execute code after TCP.Start() instead of waiting for TCP.Start() to finish like a normal C# method is being treated.
If you want TCP.Start() to be run in parallel, you should create a new Task in which you call the method like in the following code (I might have flunked on the proper syntax)
internal async void Init()
{
(..)
Task.Run(async () => await TCP.Start());
}
Now the TCP.Start() method will be executed in parallel to the rest of the application.
Read more on async and await here

Android using AsyncTask to update the UI

I want to know when the asynctask is finished, such that I could update the UI.
Can anybody help???? thanks!!!
public String[] getinfo(int id) {
String[] QueueNo = null;
try {
new DLfromServer().execute("url link"); // this is the asynctask
// want to do stuff here after the asynctask is completed
// actually I want to return a string result after the task is finished....
}
} catch (JSONException e) {
Log.e("GetJSON", "Err:", e);
}
return QueueNo;
}
want to know when the asynctask is finished, such that I could update
the UI.
Yes, you can use onPostExecute method which call on UI Thread after doInBackground execution is completed.
if you want to get data back on Main UI Thread then use AsyncTask.get() method for executing AsyncTask because this method make wait on UI Thread until doInBackground execution is completed .
String str_result= new DLfromServer().execute("url link").get();
// now use str_result for Updating result
NOTE :- you will need to call AsyncTask.get() inside an Thread instead of Main UI Thread otherwise calling of get() method will freeze Main Thread until doInBackground execution is complete

Log to Elmah in async Task

I need some Elmah logging in a async task executing on my webserver. But when I try to log the error it fails because of the HttpContext.
var httpContext = HttpContext.Current;
Task.Factory.StartNew(() =>
{
HttpContext.Current = httpContext;
try
{
//Execute some code
}
catch (Exception ex)
{
//Generate some error for the user and log the error in Elmah
try
{
ErrorLog.GetDefault(HttpContext.Current).Log(new Error(ex));
}
catch(Exception ex)
{
}
}
});
To get the progress for the task I implemented some polling mechanism. Currently none of the errors are logged to Elmah which make it difficult to solve them.
Also providing the context as parameter doesn't work.
It doesn't work. I get an ArgumentException telling me the expected value doesn't fall within the expected range. With the following stacktrace:
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name)
at System.Web.HttpRequest.AddServerVariableToCollection(String name)
at System.Web.HttpRequest.FillInServerVariablesCollection()
at System.Web.HttpServerVarsCollection.Populate()
at System.Web.HttpServerVarsCollection.Get(String name)
at Elmah.ErrorLog.InferApplicationName(HttpContext context)
at Elmah.ErrorLog.GetDefaultImpl(HttpContext context)
at Elmah.ServiceContainer.GetService(Type serviceType)
at Elmah.ServiceCenter.GetService(Object context, Type serviceType)
at Elmah.ErrorLog.GetDefault(HttpContext context)
at Bis.Utilities.Log.ElmahErrorLog.TryLogError(Exception exeption) in D:\Users\A500535\Documents\Projecten\Biobank\Bis\src\Utilities\Log\ElmahErrorLog.cs:line 13
Below is one ugly hack that might get the job done. Essentially, it creates an Error object on a bogus Exception (the prototype) so that the context can be captured while the request is still in flight. Later, when the task started as a result of the request fails, another Error object is created off the actual exception that occurred and then the interesting and contextual bits are selectively copied off the earlier prototype. Unfortunately, the prototype Error has to be created whether or not an exception will occur.
// Create an error that will capture the context
// and serve as a prototype in case a real exception
// needs logging
var prototype = new Error(new Exception(), context);
Task.Factory.StartNew(() =>
{
try
{
// Execute some code
}
catch (Exception ex)
{
// Generate some error for the user and log the error in ELMAH
try
{
// Create a new error without contextual information
// but then copy over the interesting bits from the
// prototype capture at time of request.
var error = new Error(ex)
{
HostName = prototype.HostName,
User = prototype.User,
};
error.ServerVariables.Add(prototype.ServerVariables);
error.QueryString.Add(prototype.QueryString);
error.Cookies.Add(prototype.Cookies);
error.Form.Add(prototype.Form);
ErrorLog.GetDefault(null).Log(error);
}
catch(Exception)
{
}
}
});
When you start a new thread it doesn't get the HttpContext structure. Since Elmah logging requires the HttpContext data, it will fail.
See the following QA:
Elmah Does not email in a fire and forget scenario
for me this worked in a async task called with Task.Run:
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new NotSupportedException("elmah logging test")));

Resources