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).
Related
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
}
}
}
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
I have a simple windows service written, here is its skeleton:
internal class ServiceModel {
private Thread workerThread;
private AutoResetEvent finishedEvent;
private Int32 timeout = 60000*15;
public void Start() {
this.workerThread = new Thread(this.Process);
this.finishedEvent = new AutoResetEvent(false);
this.workerThread.Start();
}
public void Stop() {
this.finishedEvent.Set();
this.workerThread.Join(30000);
}
public void Process() {
while(!this.finishedEvent.WaitOne(timeout)) {
// run things here
}
}
}
the first thing
The first thing that I can't understand is that service waits one timeout before running. Would rewriting the new AutoResetEvent(false); to new AutoResetEvent(true); cause a service to start without waiting?
the second thing
Due to some internal reasons (requesting data from external server/service, exception handling) sometimes it is not enough to wait that fixed 15..30-minutes timeout.
How do I rewrite it to work without a fixed timeout?
Do I need to remove that AutoResetEvent instance at all and run Process body inside an infinite loop?
public void Process() {
while(true) {
// run things here
}
}
edit. try-catch/lock
In Process method there is a global try-catch block:
public void Process() {
do {
try {
// processing goes here
}
catch(Exception ex) {
Logger.Log.Warn(ex); // or Log.Fatal(ex)...
}
}
while(true);
}
if I use a synchronization object where do I put the lock statement so that I'm able to call break when isStopped is true?
You don't have to deal with low-level thread and synchronization primitives API. Consider using Task Parallel Library (TPL). It's easy to implement OnStop using TPL cancellation framework:
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
CancellationTokenSource _mainCts;
Task _mainTask;
public Service1()
{
InitializeComponent();
}
async Task MainTaskAsync(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
// ...
await DoPollingAsync(token);
// ...
}
}
protected override void OnStart(string[] args)
{
_mainCts = new CancellationTokenSource();
_mainTask = MainTaskAsync(_mainCts.Token);
}
protected override void OnStop()
{
_mainCts.Cancel();
try
{
_mainTask.Wait();
}
catch
{
if (!_mainTask.IsCanceled)
throw;
}
}
}
}
Inside MainTaskAsync you can use Task.Run for any CPU-bound work items.
using Threads you can achieve your requirement using the following code:
internal class ServiceModel {
private Thread workerThread;
private object syncLock = new object();
private bool stop = false;
public void Start() {
this.workerThread = new Thread(this.Process);
this.workerThread.Start();
}
public void Stop() {
lock(syncLock) stop = true;
this.workerThread.Join(30000);
}
public void Process() {
while(true){
//your stuff here.
lock(syncLock)
{
if(stop)
break;
}
Thread.Sleep(30000);
}
}
}
So I have a simple test using Monitor.Wait with a timeout set for three seconds. It's my understanding that, when the time expires, a virtual pulse is sent to the monitor to release the wait. In my test, however, that never seems to happen. Can someone explain what's going on. Here's my test code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace BlockingMethodFoo
{
class Program
{
static void Main(string[] args)
{
WaitFoo foo = new WaitFoo();
foo.StartMethod();
Console.WriteLine("Done. Press enter");
Console.ReadLine();
}
}
public class WaitFoo
{
private object _waitObj = new object();
private string _message = string.Empty;
public void StartMethod()
{
Thread waitThread = new Thread(new ThreadStart(new Action(() => { WaitMethod(); })));
_message = string.Empty;
Console.WriteLine("Starting wait");
_message = "Time Out";
lock (_waitObj)
{
waitThread.Start();
Monitor.Wait(_waitObj, TimeSpan.FromSeconds(3));
}
Console.WriteLine(_message);
}
private void WaitMethod()
{
lock (_waitObj)
{
_message = Console.ReadLine();
Monitor.Pulse(_waitObj);
}
}
}
}
Monitor.Wait will return false if the timeout expires and it couldn't get the lock.
http://msdn.microsoft.com/en-us/library/tdc87f8y.aspx
You have to check the return of Monitor.Wait and for example throw a TimeOutException if you see fit.
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)
{
}
}
}
}