I need to a background long running thread from the asp.net application.
BTW,the method fetches something from external data source period and maybe exception happens, I provide some ways to fullfill this task, please advice which way is best, please advice if there is better way.
Way1=Looping when exception happens.
static void LongRunningMethod()
{
do
{
try
{
//fetch something from external period and maybe exception happens.
Thread.sleep(100000);
}
catch(Exception ex)
{
//log exception..
}
} while (true);
}
Way2=Running the following method period by something like timer, and open a new thread when exception happens.
static void LongRunningMethod()
{
try
{
//fetch something from external period and maybe exception happens.
Thread.sleep(100000);
}
catch(Exception ex)
{
//log exception..
Thread T2 = new Thread(LongRunningMethod);
T2.Start();
}
}
Way3=Call itself when exception happens.
static void LongRunningMethod()
{
try
{
//fetch something from external period and maybe exception happens.
Thread.sleep(100000);
}
catch(Exception ex)
{
//log exception..
LongRunningMethod();
}
}
I will use none of the three. In fact, I seldom build interval tasks base on ASP.NET because:
1. The start of the task is out of control
Based on ASP.NET the task has to be started/registered on Application_Start method, which is triggered by the first request, that means your tasks is started when the first request comes. Theoretically it can be long time after your application is deployed.
2. The end of the task is out of control
The web servers (thinking IIS) can be configured as recycle-on-demand (AFAIK this is the default behavior). That is, your thread may be killed when executing. Under most circumstances you need to deal with the persistence of your tasks and states, and add retrying codes and etc... That's a nightmare!
For me it's a better idea to use a windows service, or the task scheduler function of windows, the latter is even easier because you don't need to write a timer or interval call codes. It's more stable, less code, and friendly logs in the event viewer! That's really make everything easier.
I like to use System.ComponentModel.BackgroundWorker:
static BackgroundWorker looper = new BackgroundWorker();
static bool isRunning = true;//you can set this to false when closing
public static void initialize(){
looper.DoWork+= doLoop;
looper.RunRunWorkerAsync();
}
private static void doLoop(object sender, DoWorkEventArgs e){
while(isRunning){
//do looping code
System.Threading.Thread.Sleep(5000);
if(!isRunning)
break;
}
}
PS - sorry for weird spacing - I edited this directly in the code window.
Related
I have a windows service with a listener that runs a loop within a task that listens to ServiceBus. If the connection goes down or some other problem occurs I want to start the listener task again. Since I do not do any await on the task as it is should run forever I do need to use ContinueWith and check if the exception has occurred. If it did I want to start exactly the same process.
So the question is: Is it safe to do it this way with regards to execution context, memory, stack trace or some other things I have not thought about?
The code seems to run all fine and reconnects if the network was down and came back online, stack trace for the exceptions seems correct as well but I am afraid of some pitfalls I have not thought about.
private void StartReceiving(string connectionString)
{
_receiverHost
.StartReceiving(connectionString)
.ContinueWith(c =>
{
if (c.IsFaulted)
{
Thread.Sleep(60000);
StartReceiving(connectionString);
}
}
});
}
To answer your question:
"Is it safe to do it this way with regards to execution context, memory, stack trace or some other things I have not thought about?"
Yes; there is no issues in regards of any of the mentioned areas that i can think of.
You basically exit the previous task and enter a new task. Your memory is cleaned when you continue the following task and the stacktrace is starting at the task creating the execution.
However I'd rather comment on the issues it introduces in regards of error handling and breaking the execution, which by this implementation does not help you to find the error, connect to an alternative address or some other logic you may introduce. In my opinion you introduce an unexpected complexity in this implementation.
If I had to implement this class, I would rather raise a disconnected event which the class using this object has to solve. This will give you a much wider range of opportunities, e.g. notifying other dependent classes.
Furthermore, freezing a thread is usually not a good solution. I'd rather start a timer or something similar.
I tried your code in some extra code as follows, and I wasn't able to see any issue with execution context, memory, stack trace.
public class Receiver
{
public async Task StartReceiving(string connectionString)
{
var task = Task.Run(() =>
{
try
{
throw new Exception("connection lost");
}
catch (Exception)
{
/* log the exception, or something */
throw;
}
});
await task;
}
}
public class Server
{
ILog log = LogManager.GetLogger<Server>();
public bool IsStopped { get; private set; } = false;
private Receiver _receiverHost = new Receiver();
public void StartReceiving(string connectionString)
{
_receiverHost
.StartReceiving(connectionString)
.ContinueWith(async c =>
{
if (c.IsFaulted)
{
var n = Process.GetCurrentProcess().Threads.Count;
var timestamp = DateTime.UtcNow;
await Task.Delay(1000);
log.Debug($"Task Delay: {(DateTime.UtcNow - timestamp).TotalSeconds} seconds");
StartReceiving(connectionString);
}
});
}
}
[TestFixture]
public class TestServerRetry
{
[TestCase]
public async Task TestRetry()
{
var server = new Server();
server.StartReceiving("test connection");
while (!server.IsStopped)
await Task.Delay(100);
}
}
Is Looping inside a task really recommended?
example code:
public void doTask(){
Task.Factory.StartNew(() => {
do{
// do tasks here.... call webservice
}while(true till cancelled)
});
}
any answers would be great! :)
because it is a case for my webservice calling right now, and the memory consumption goes out of control.
So may I ask, is looping inside a task really good or not recommended at all?
As Requested by SLC, heres the code:
CancellationTokenSource tokenSrc;
Task myTask;
private void btnStart_Click(object sender, EventArgs e)
{
isPressed = !isPressed;
if(isPressed)
{
tokenSrc = new CancellationTokenSource();
myTask = Task.Factory.StartNew(() =>
{
do{
checkMatches(tokenSrc.Token);
}while(tokenSrc.IsCancellationRequested != true);
}, tokenSrc.Token);
}
else {
try{
tokenSrc.Cancel();
// Log to notepad
}
catch(Exception err){
// Log to notepad
}
finally {
if(myTask.IsCanceled || myTask.IsCompleted || myTask.isFaulted) {
myTask.Dispose();
}
}
}
}
private void checkMatches(CancellationTokenSource token)
{
try
{
if(!token.IsCancellationRequested)
{
//Create Endpoint...
//Bypass ServCertValidation for test purposes
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate {return true;});
using(WebServiceAsmx.SoapClient client = new....)
{
client.CheckResp response = client.chkMatch();
// if's here for the response then put to logs
}
}
}
catch(Exception err)
{
// err.toLogs
}
}
It's perfectly fine to do this, especially if your task runs constantly, for example picking up a message queue.
while (not shutting down)
get next email to send
if exists next email to send
send
else
wait for 10 seconds
wend
Ensure that you have a way to get out if you need to cancel it, like you've done with a flag, and you should be fine.
Regarding webservices:
You should have no problem calling the webservice repeatedly, nor should it cause any memory spikes. However, you should make sure your initialisation code is not inside the loop:
BAD
while (notShuttingDown)
make a new connection
initialise
make a call to the service()
wend
GOOD
make a new connection
initialise
while (notShuttingDown)
make a call to the service
wend
Depending on your webservice it might be more optimal to create a batch operation, for example if your service is HTTP then hitting it repeatedly involves a lot of overhead. A persistent TCP connection might be better because it could be creating and destroying a lot of objects to make the calls.
For example
slow, lots of overhead:
myRecords = { cat, dog, mouse }
foreach record in myRecords
webservice check record
endforeach
faster:
myRecords = { cat, dog, mouse }
webservice check [myRecords] // array of records is passed instead of one by one
Debugging: The most likely risk is that somehow the task is not being disposed correctly - can you add this to your method to debug?
myTask = Task.Factory.StartNew(() =>
{
Console.Writeline("Task Started");
do{
checkMatches(tokenSrc.Token);
Thread.Sleep(10); // Some pause to stop your code from going as fast as it possibly can and putting your CPU usage to 100% (or 100/number of cores%)
}while(tokenSrc.IsCancellationRequested != true);
Console.Writeline("Task Stopped");
}
You might have to change that so it writes to a file or similar depending on if you have a console.
Then run it and make sure that only 1 task is being created.
I have a long running Console application (3 hrs) which I need to kill with an Exception in certain circumstances. The reason for killing this batch is that it is monitored by operators and controlled by an enterprise scheduler. An unhandled exception will alert them and its message used by the on-call support.
Ideally, I want a background thread running as a TPL Task to check for these database defined criteria, and if encountered throw an exception to fail the process. Throwing an exception in a Task does not kill the main thread. I have tried the following, running a ContinueWith Task on the main's scheduler but it does not affect main.
static void Main(string[] args)
{
var mainThread = TaskScheduler.Current;
var taskDb = new Task<bool>(RunDb, TaskCreationOptions.LongRunning);
var taskHandle = taskDb.ContinueWith(b => Check(b.Result), mainThread);
taskDb.Start();
//do stuff
}
static bool RunDb()
{
//check database in loop
//if validation failed return false
return false;
}
static void Check(bool successful)
{
//check database in loop
//if validation failed return false
if(!successful)
throw new Exception("batch failed for these reasons...");
}
The only possible solution I've arrived at is modify a global property from within the ContinueWith action, and query this property from within the main thread, throwing an exception.
I've had a good look around the web and while there's plenty on cancelling threads from main, there's nothing about killing main from a background thread.
You can use Environment.FailFast everywhere to shutdown your application with an exception. This works from a background thread as well:
Task.Run(() => Environment.FailFast("Fail", new Exception("batch failed for these reasons...")));
However, I think a more robust design would be to have a system wide CancellationToken that you can cancel from your task that brings down the entire application gracefully.
Environment.Exit() is probably the easiest way. For example, the following program will exit after printing about 10 numbers, rather than the full 100.
public static void Main(string[] args)
{
Task.Run(() =>
{
Thread.Sleep(1000);
Console.Out.WriteLine("Something has gone terribly wrong!");
System.Environment.Exit(1);
});
for (int i = 0; i < 100; i++)
{
Console.Out.WriteLine(i);
Thread.Sleep(100);
}
}
I'm trying to write a program that catches the HTTP get requests.
I have found Fiddler-core a genius library that should do exactly what I want.
The thing is, I'm trying to execute a big piece code-work inside the void FiddlerApplication_BeforeRequest(Session oSession) and it seems to block all the request and damage my surfing speed a great deal.
I have tried to use threads/tasks with no avail.
What am I doing wrong?
This is my code:
public event RequestCapture RequestCaptured;
private CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
//...stat public function:
public void RunWatch() {
Fiddler.FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;
Fiddler.FiddlerApplication.Startup(0, FiddlerCoreStartupFlags.Default);
}
void FiddlerApplication_BeforeRequest(Session oSession)
{
if (RequestCaptured != null)
{
CancellationToken ct = cancelTokenSource.Token;
Task.Factory.StartNew(() =>RequestCaptured(oSession.fullUrl), ct);
//Handle the event in a new thread, so the Listener will continue to listen
}
}
//close public function:
public void Close() {
try
{
FiddlerApplication.Shutdown();
cancelTokenSource.Cancel();
}
catch { }
}
now i have i different class that do that:
public Form1()
{
Listiner = new HttpWatcher.Listner();
Listiner.RequestCaptured += RequestCaptured;
Listiner.RunWatch();
}
void RequestCaptured(string url)
{
System.Threading.Thread.Sleep(10000);
}
edit
The question is: Is there a better way using fiddler-core? or am i to build a simple proxy for that? using something else? Thanks!
edit2
I have edited the code, so it would fill the missing parts.
Just to be clear here, FiddlerCore processes each Session on a threadpool thread. If you need blocking behavior, there's no need to spin up an additional thread or anything like that. If you don't need to process things in a blocking manner, then feel free to queue the data on a background queue and use tasks or another asynchronous mechanism to perform processing.
You should explain exactly what you mean when you say damage my surfing speed a great deal, and whether or not you see different behavior when using Fiddler rather than your application.
Consider the following code which uses basic Task library functionality with a CancellationTokenSource. It starts up a thread which fills a Dictionary with prices and reads the data from an SQL server db. The thread ends after about 10 minutes and every 2 hours it is fired up again, calling Cancel first in case the thread was still running.
private CancellationTokenSource mTokenSource = new CancellationTokenSource();
internal Prices(Dictionary<string, Dealer> dealers)
{
mDealers = dealers;
mTask = Task.Factory.StartNew
(() => ReadPrices(mTokenSource.Token), mTokenSource.Token);
}
internal void Cancel()
{
mTokenSource.Cancel();
}
private void ReadPrices(CancellationToken ct)
{
using (SqlConnection connection =
new SqlConnection(ConfigurationManager.AppSettings["DB"]))
{
connection.Open();
var dealerIds = from dealer in mDealers.Values
where dealer.Id != null
select dealer.Id;
foreach (var dealerId in dealerIds)
{
if (!ct.IsCancellationRequested)
{
FillPrices(connection);
}
else
break;
}
}
}
Now at some point the application crashes with the following exception in the event log.
Application: Engine.exe Framework Version: v4.0.30319 Description: The
process was terminated due to an unhandled exception. Exception Info:
System.AggregateException Stack: at
System.Threading.Tasks.TaskExceptionHolder.Finalize()
It must have to do with the code here because the Tasks library isn't used anywhere else but I cant figure out what is wrong with the code. Does anyone have an idea what could be wrong here?
Tasks like to feel listened to. It sounds like something isn't happy. You do get a "last chance" to hear it out, though:
TaskScheduler.UnobservedTaskException += (sender, args) =>
{
foreach (var ex in args.Exception.InnerExceptions)
{
Log(ex);
}
args.SetObserved();
};
Note this isn't intended as the fix - it is intended to let you see what Task is exploding and with what error. The SetObserved() will prevent it killing your application. But the fix here is ideally:
don't let your tasks throw,
or make sure that you're there to check the status of the task later
It is quite possibly not happy with your cancellation detection. IIRC the preferred way to do that would be:
foreach(...) {
if(ct.IsCancellationRequested) {
// any cleanup etc
ct.ThrowIfCancellationRequested();
}
...
}
or more simply if no cleanup is needed, just:
foreach(...) {
ct.ThrowIfCancellationRequested();
...
}
Equally, it could just be a data access exception. There are any number of exceptions that can happen when talking to a database. Timeout, deadlock, cannot-connect, etc.