Exceptions Tasks with ContinueWith - c#

Example 1. The exception of the task from which the ContinueWith method is called (t1) does not apply to the task created by this method (t2). And you need to handle this exception using wait methods.
Question 1: Do I understand correctly?
Example 2. It says here:
If the continuation is an attached child task that was created by
using the TaskContinuationOptions.AttachedToParent option, its
exceptions will be propagated by the parent back to the calling
thread, as is the case in any other attached child.
As I understand it, this means the exception of the task created by the ContinueWith method with TaskContinuationOptions.AttachedToParent (t2) should be extended to the task from which the method (t1) was called. However, I don't see any exceptions.
Question 2: Do I understand correctly? Why there are no exceptions? How should the exception be handled in this case?
Question 3. What are the ways to handle exceptions other than using wait methods in case of using method ContinueWith?
Example 1. Code:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
void MyMethod1()
{
Console.WriteLine(1);
Thread.Sleep(1000);
throw new Exception();
}
void MyMethod2(Task t)
{
Console.WriteLine(2);
Thread.Sleep(1000);
}
Task t1 = new Task(MyMethod1);
t1.Start();
Task t2 = t1.ContinueWith(MyMethod2);
t1.Wait(); //AggregateException. Inner Exception: Exception_WasThrown
t2.Wait();
}
}
}
Example 2. Code:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
void MyMethod1()
{
Console.WriteLine(1);
Thread.Sleep(1000);
}
void MyMethod2(Task t)
{
Console.WriteLine(2);
Thread.Sleep(1000);
throw new Exception();
}
Task t1 = new Task(MyMethod1);
t1.Start();
Task t2 = t1.ContinueWith(MyMethod2, TaskContinuationOptions.AttachedToParent);
t1.Wait(); //No Exception
}
}
}

Related

Not seeing output after using Task delay

I am using an online editor for testing some C# code : https://repl.it/
I am not able to get the task after Task.Delay.
Why is this C# code not working as intended?
using System.IO;
using System;
using System.Reflection;
using System.Threading.Tasks;
class Input {
public Input() {
}
public async void hello()
{
Console.WriteLine("some task");
await Task.Delay(1000);
Console.WriteLine("after some time");
}
}
class SomeExample {
public static void Main(string[] args) {
Input std1 = new Input( );
std1.hello();
}
}
Method hello should return Task, not void. Method Main should be async Task to be able to await hello. Also you need to await std1.hello() call:
public async Task hello()
{
Console.WriteLine("some task");
await Task.Delay(1000);
Console.WriteLine("after some time");
}
public static async Task Main(string[] args)
{
Input std1 = new Input( );
await std1.hello();
}
What you have now is situation when Main method finishes its execution before hello method (because it not awaited).
Fixes: Change your method return type from void to Task. Make the console wait by adding Console.ReadLine() so that you can see the output ("after some time") and lastly, tell the method to wait and don't finish execution by adding Wait().
Hope this works.
class Input
{
public Input()
{
}
public async Task hello()
{
Console.WriteLine("some task");
await Task.Delay(1000);
Console.WriteLine("after some time");
Console.ReadLine();
}
}
class SomeExample
{
public static void Main(string[] args)
{
Input std1 = new Input();
std1.hello().Wait();
}
}
For now it seems this code is doing my work. I don't need to use async or Task keywords.
using System.IO;
using System;
using System.Threading.Tasks;
class Input
{
public Input()
{
}
public void hello()
{
Console.WriteLine("some task");
Task.Delay(1000).Wait();
Console.WriteLine("after some time");
}
}
class SomeExample
{
public static void Main(string[] args)
{
Input std1 = new Input();
std1.hello() ;
}
}

Starting a task using delegate in C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskStart
{
class Program
{
private static void PrintMessage()
{
Console.WriteLine("Hello Task library!");
}
static void Main(string[] args)
{
//method 1
//Task.Factory.StartNew(() => { Console.WriteLine("Hello Task library!");});
//method 2
//Task task = new Task(new Action(PrintMessage));
//task.Start();
//method3
Task task = new Task(delegate { PrintMessage(); });
task.Start();
}
}
}
I am trying to get my Console app to print the message Hello Task library!. I am currently using method 3 below. For some reason the app shows a blank screen with the message Press any key to continue when I press Ctrl + F5 on VS2015.
Why is my message not getting printed.
This is because you are not waiting for your task to complete. Try add task.Wait() to the end of your method and see the result should be displayed.
Update: If you are using Visual Studio 2017 Update 15.3 or above and C# 7.1, there is support for async Main now.
You can modify your code as follows:
class Program
{
private static void PrintMessage()
{
Console.WriteLine("Hello Task library!");
}
static async Task Main()
{
var task = new Task(PrintMessage);
task.Start();
await task;
}
}

The simplest possible infinitely repeat

I need the simplest possible Timer to repeat my code infinitely every 5 seconds. No external classes or whatnot.
Just:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Now the following code will be repeated over and over");
//////////////// FOLLOWING CODE /////////////////
/* the repeated code */
//////////////// END OF FOLLOWING CODE /////////////////
}
}
How can I do that?
Use while(true) with Thread.Sleep
using System.Threading;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Now the following code will be repeated over and over");
while(true)
{
//////////////// FOLLOWING CODE /////////////////
/* the repeated code */
//////////////// END OF FOLLOWING CODE /////////////////
Thread.Sleep(5000);
}
}
}
Simplest form of it :
using System.Threading;
static void Main(string[] args)
{
bool breakConditionFlag = false;
ManualResetEvent waitHandler = new ManualResetEvent(false);
while(breakConditionFlag)
{
//Your Code
waitHandler.WaitOne(TimeSpan.FromMilliseconds(1000)); // 1000 is the Arbitary value you can change it to Suit your purpose;
}
}
Why ManualResetEvent ?
The event makes more efficient use of the processors- you're not having to wake the parent thread up to poll. The kernel will wake you up when the event fires.
Use Timer.
static void Main(string[] args)
{
Timer timer = new System.Threading.Timer((e) =>
{
Console.WriteLine("Now the following code will be repeated over and over");
}, null, 0, (int)TimeSpan.FromSeconds(5).TotalMilliseconds);
Console.Read();
}
Here I have called Console.WriteLine multiple times, you can write your code block instead of it.
You can use Thread.Sleep(5000); But again its also external class according to the OP.
But I would suggest a better solution using Async and Await. One more thing you should have a termination condition, so that you dont produce an infinite call to avoid unnecessary memory consumption.
public static async Task RepeatActionEveryInterval(Action action, TimeSpan interval, CancellationToken cancelToken)
{
while (true)
{
action();
Task task = Task.Delay(interval, cancelToken);
try
{
await task;
}
catch (TaskCanceledException)
{
return;
}
}
}
static void Main(string[] args)
{
CancellationTokenSource cancelToken = new CancellationTokenSource(TimeSpan.FromSeconds(50));
Console.WriteLine("Start");
RepeatActionEveryInterval(() => Console.WriteLine("Repeating Code"), TimeSpan.FromSeconds(5), cancelToken.Token).Wait();
Console.WriteLine("End");
Console.Read();
}
In this example this code will write till 50 seconds.
Use this code for call your function recursively for every 5 seconds.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace recurssiveWithThread
{
class Program
{
static void Main(string[] args)
{
RecWork();
}
public static int i = 0;
public static void RecWork()
{
// Do the things whatever you needed here
i++;
Console.WriteLine(i);
//Thread to make the process to sleep for sometimes
Thread.Sleep(5000);
//Call your function here
RecWork();
}
}
}
Use BackgroundWorker class:
Reference links:
Background worker
If you are using framework >= 4.5.2 QueueBackgroundWorkItem
QueueBackgroundWorkItem

Create Async thread using Thread Class in WPF

I am creating a thread using
public static void Invoke(ThreadStart method)
{
Thread th = default(Thread);
try
{
th = new Thread(method);
th.Start();
}
catch (Exception ex)
{ }
}
and I am calling it as
Invoke(new Threading.ThreadStart(method_name));
In WPF, I need that what this thread does should not hang UI (i.e. an ASync thread should start). What should I do?
If you are using .net 4.5 you can do
Task.Run( () =>
{
// your code here
});
In .net 4.0 you can do:
Task.Factory.StartNew(() =>
{
// your code here
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
If you are only using the Thread fore responsive UI look at the System.ComponentModel.BackgroundWorker
this is typiccaly used for responsive UI
If you use the latest version of the framwork, you could also look at the async keyword
Async/await vs BackgroundWorker
If you are using WPF, you can Use BeginInvoke. What is exactly wrong with your Code?
This works fine:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace AsyncTest
{
class Program
{
static void Main(string[] args)
{
// First Counter (Thread)
Invoke(new ThreadStart(Do));
Thread.Sleep(10000);
// Second Counter (Thread)
Invoke(new ThreadStart(Do));
Console.ReadLine();
}
public static void Do()
{
for (int i = 0; i < 10000000; i++)
{
Console.WriteLine("Test: " + i.ToString());
Thread.Sleep(100);
}
}
public static void Invoke(ThreadStart ThreadStart)
{
Thread cCurrentThread = null;
try
{
cCurrentThread = new Thread(ThreadStart);
cCurrentThread.Start();
}
catch (Exception ex)
{
}
}
}
}

Catching async exception in main thread

Here's my code:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
namespace TestAsync
{
class Program
{
private const string conn = "Data Source=UNREACHABLESERVER;Initial Catalog=master;Integrated Security=True";
static void Main(string[] args)
{
try
{
TestConnection();
}
catch
{
Console.WriteLine("Caught in main");
}
}
private static async void TestConnection()
{
bool connected = false;
using (var tokenSource = new CancellationTokenSource())
using (var connection = new SqlConnection(conn))
{
tokenSource.CancelAfter(2000);
try
{
await connection.OpenAsync(tokenSource.Token);
connected = true;
}
catch(TaskCanceledException)
{
Console.WriteLine("Caught timeout");
}
catch
{
Console.Write("Caught in function");
}
if (connected)
{
Console.WriteLine("Connected!");
}
else
{
Console.WriteLine("Failed to connect...");
throw(new Exception("hi"));
}
}
}
}
}
The output is:
Caught timeout
Failed to connect...
But then my program terminates with an unhandled exception. Instead, I'm wanting my program to have the thrown exception handled in the main thread and print out Caught in main. How can I make that work?
EDIT
Here's my updated code that works the way I want:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
namespace TestAsync
{
class Program
{
private const string conn = "Data Source=UNREACHABLESERVER;Initial Catalog=MyFiles;Integrated Security=True";
static void Main(string[] args)
{
try
{
TestConnection().Wait();
}
catch
{
Console.WriteLine("Caught in main");
}
Console.ReadLine();
}
private static async Task TestConnection()
{
using (var tokenSource = new CancellationTokenSource())
using (var connection = new SqlConnection(conn))
{
tokenSource.CancelAfter(2000);
await connection.OpenAsync(tokenSource.Token);
}
}
}
}
This is not possible. Your call to TestConnection() will return (and thus execution on the main thread will continue) once your first await is encountered. Your catch blocks and throwing the exception will execute on another thread and go unobserved by the main thread.
This one just one reason why async void should be avoided. If you need to write an async void function, it must be completely self-contained (including error handling logic). You would be much better off writing an async Task function. The simplest approach would be to modify your call in the Main method to this:
TestConnection().Wait()
This will, of course, cause the main thread to block while executing the function (you'll also have to change the signature to async Task before this will compile).

Categories