Task unable to timeout - c#

I have a implemented a simple task using TPL. It waits for 10 seconds to execute and returns true/false.
var checkCFOPTask = Task.Run(() => CheckCFOPExists());
checkCFOPTask.Wait(TimeSpan.FromSeconds(10));
if (checkCFOPTask.Result)
{
}
else
{
}
The problem is my code is stuck within the if statement.
if (checkCFOPTask.Result)
Each time I pause the debugger it still keeps waiting on the above line of code. This happened for the first time. Ideally it should return true/false within 10 seconds.
Below are the function definitions-
CheckCFOExists: Executed by the task.
private bool CheckCFOPExists()
{
bool found = false;
try
{
while (!found)
{
try
{
if (ieDriver.FindElement(By.Id("popup_message")).Text == "Não existem itens para realizar o rateio.")
{
ResetInvoiceSearchScreen();
break;
}
}
catch (Exception ex)
{
}
try
{
if (arrCFOPList.Contains(ieDriver.FindElement(By.Id("vendorNF.cfopOperCode")).GetAttribute("value")))
{
found = true;
}
}
catch (Exception ex)
{
}
}
}
catch (Exception ex)
{
}
return found;
}
ResetInvoiceSearchScreen: Executed within the above function
private void ResetInvoiceSearchScreen()
{
try
{
ieDriver.FindElement(By.Id("popup_ok")).Click();
ieDriver.FindElement(By.Id("ltmCnpjCpf")).Clear();
ieDriver.FindElement(By.Id("notaFiscalNbr")).Clear();
ieDriver.FindElement(By.Id("inbNotaFiscalId")).Clear();
ieDriver.FindElement(By.Id("seriesFrmCd")).Clear();
}
catch (Exception ex)
{
}
}
Is there something else that is needed ensure the function times out correctly? Please let me know if I can provide some more details.
Edit
I see the below message for checkCFOPTask.Result in the immediate window of Visual Studio-
Id = Cannot evaluate expression because the code of the current method is optimized., Status = Cannot evaluate expression because the code of the current method is optimized., Method = Cannot evaluate expression because the code of the current method is optimized., Result = Cannot evaluate expression because the code of the current method is optimized.

It looks like you will need to add time-out support to the method that you're calling - because if it doesn't find the thing it's looking for it will loop forever.
The easiest way to do this is to pass a CancellationToken to the method. You should also factor out the testing code into a separate method that returns bool.
Also note that you have a busy loop, which is generally not a good idea when polling! It's better to introduce a small sleep when polling if the thing you're polling for isn't available. (Note: Polling in general is not a good approach if you have a better way of checking for something, but it doesn't look like there's anything else you can use here, so polling will have to do.)
You can write your method like so (I've omitted the code that polls for the thing you're looking for in order to concentrate on the other logic):
private bool CheckCFOPExists(CancellationToken cancel)
{
TimeSpan retryDelay = TimeSpan.FromMilliseconds(500);
while (true)
{
if (tryToFindTheThing()) // Blocking call.
return true;
if (cancel.WaitHandle.WaitOne(retryDelay))
return false;
}
}
bool tryToFindTheThing()
{
return false; // Your implementation goes here.
}
Then to call this and have a 10-second timeout you would do something like this (compilable console app):
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
var test = new Program();
// Create a cancellation token source that cancels itself after 10 seconds:
var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10));
// Create and run the task:
var sw = Stopwatch.StartNew();
var checkCFOPTask = Task.Run(() => test.CheckCFOPExists(cancellation.Token));
Console.WriteLine("Waiting for task to finish.");
Console.WriteLine($"Task returned: {checkCFOPTask.Result} after {sw.ElapsedMilliseconds} ms");
}
private bool CheckCFOPExists(CancellationToken cancel)
{
TimeSpan retryDelay = TimeSpan.FromMilliseconds(500);
while (true)
{
if (tryToFindTheThing()) // Blocking call.
return true;
if (cancel.WaitHandle.WaitOne(retryDelay))
return false;
}
}
bool tryToFindTheThing()
{
return false; // Your implementation goes here.
}
}
}

Before using the Result you need to check if your task actually is completed with Task.IsCompleted.
if (checkCFOPTask.IsCompleted && checkCFOPTask.Result)

Related

C# AWS Lambda and Thread.Sleep()

I have a foreach loop running inside an AWS lambda, with a Thread.Sleep(2000) to throttle execution. However, the code doesn't seem to pause: I've logged timestamps before and after its execution. Here's a simplified version of the method:
private async Task<string> ExecuteAutoRetryRequest(string url)
{
string html = String.Empty;
int numberOfRetry = 3;
while (numberOfRetry > 0)
{
try
{
html = await ExecuteGetRequest(url);
if (!string.IsNullOrEmpty(html) && !html.Contains("Access Denied"))
{
break;
}
}
catch (Exception ex)
{
await LogException(ex.Message);
}
// Wait two seconds and try again
Console.WriteLine(DateTime.Now.ToString());
Thread.Sleep(2000);
Console.WriteLine(DateTime.Now.ToString());
numberOfRetry--;
}
return html;
}
I call it like so var htmlSnapShotResult = await ExecuteAutoRetryRequest(url);
I'm sure this is something basic about how lambdas operate that I'm unaware of, but any help would be appreciated.
Alexander's comment above is the correct answer: the following executes the pause correctly:
await Task.Delay(2000);

Whats the difference with returning Task<bool> and just returning bool

Hopefully this is a nice and simple answer.
I'm using C# MVC Web API in ASP.NET Core 1. I'm creating web methods and I've seen examples with this of returning data.
Example 1:
public async Task<IActionResult> ExampleCall([FromBody]ExampleObj model)
{
// Call some lower level function...
var result = LowerLevelCall(model);
return result;
}
And seen other examples like this.
Example 2:
public async Task<IActionResult> ExampleCall([FromBody]ExampleObj model)
{
// Call some lower level function...
var result = await LowerLevelCall(model);
return result;
}
Main difference is that Example 2 using the await operator. What's the implications of implementing the await operator? Will this free resources up rather than waiting for code to complete in Example 1?
Thanks in advance for any tips!
In your scenario, the async operator will stop the execution of the method until the result is received from LowerLevelCall. However when the execution of the method is stopped, await waits asynchronously so the thread itself is not blocked. After getting the result from LowerLevelCall the method just resumes executing synchronously.
Example 1 - If LowerLevelCall takes a long time to execute, you thread will be blocked and will just sit there and do nothing until the execution of LowerLevelCall is complete.
Example 2 - If you use await, you won't block the thread since await waits asynchronously. After LowerLevelCall finishes executing the result of the method will be assigned to your result variable.
Intro to Async And Await - This article should help you get started with async and await.
In the first example if LowerLevelCall(model); takes a long time, your result won't be returned before this method finishes and this will block current thread - you have to wait all this time doing nothing.
In the second example current thread won't be blocked and you can do something other.You will get the result asynchronously when LowerLevelCall(model); finishes.
the different is that the function with the await is wait to finish first his job before return. Now on web page that I make some test, no one from that two functions blocks the running of code, and they continues to run on a thread.
public async Task<IActionResult> ExampleCall([FromBody]ExampleObj model)
{
// Call some lower level function...
// ***Here is not return until this function is finish first.***
var result = await LowerLevelCall(model);
return result;
}
Lets look inside.... I make two functions similar to yours
public static async Task<bool> Task1()
{
await Task.Delay(10000);
return true;
}
public static async Task<bool> Task2()
{
Task.Delay(10000);
return true;
}
The final code on this two is a lot different.
With await
private void MoveNext()
{
bool flag;
int num = this.<>1__state;
try
{
TaskAwaiter awaiter;
if (num != 0)
{
awaiter = Task.Delay(0x2710).GetAwaiter();
if (!awaiter.IsCompleted)
{
this.<>1__state = num = 0;
this.<>u__1 = awaiter;
cTestClass.<Task1>d__0 stateMachine = this;
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, cTestClass.<Task1>d__0>(ref awaiter, ref stateMachine);
return;
}
}
else
{
awaiter = this.<>u__1;
this.<>u__1 = new TaskAwaiter();
this.<>1__state = num = -1;
}
awaiter.GetResult();
awaiter = new TaskAwaiter();
flag = true;
}
catch (Exception exception)
{
this.<>1__state = -2;
this.<>t__builder.SetException(exception);
return;
}
this.<>1__state = -2;
this.<>t__builder.SetResult(flag);
}
with out
// MoveNext is the name of warped function that call the thread.
private void MoveNext()
{
bool flag;
int num = this.<>1__state;
try
{
Task.Delay(0x2710);
flag = true;
}
catch (Exception exception)
{
this.<>1__state = -2;
this.<>t__builder.SetException(exception);
return;
}
this.<>1__state = -2;
this.<>t__builder.SetResult(flag);
}
Some comments
All this inline functionality of asp.net have the purpose to simplify and help for asynchronous do thread work. Have a point on desktop programming that is help to not hold the "draw" message from windows to your program, but on asp.net did not have many effects that are visible, and add a lot of overhead. If you don't know exactly how the multitask will be used it may lead on more delay than help because all are happened on server, not on client that no need this kind of multitask.

Where to handle exceptions thrown by Task

I am executing some polling IO loops in separate Tasks. Those loops may encounter exceptions. If one encounters an exception, I want to alert the caller so that it can:
log it
kill all IO threads
reset the connection
restart IO threads
The UI must remain responsive. What is the preferred method of handling this scenario? I've include an illustrative program below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskExceptionCatching
{
class Program
{
static void Main(string[] args)
{
startLoops();
System.Console.WriteLine("Type 'Exit' when you're ready to stop.");
while (System.Console.ReadLine() != "Exit")
{
System.Console.WriteLine("Seriously, just type 'Exit' when you're ready to stop.");
}
}
static private void startLoops()
{
System.Console.WriteLine("Starting fizzLoop.");
var fizzTask = Task.Factory.StartNew(new Action(fizzLoop));
System.Console.WriteLine("Starting buzzLoop.");
var buzzTask = Task.Factory.StartNew(new Action(buzzLoop));
}
static private void fizzLoop()
{
while (true)
{
//simulate something error prone, like some risky IO
System.Threading.Thread.Sleep(200);
bool isErr = (new Random().Next(1, 100) == 10);
if (isErr)
throw new Exception("Fizz got an exception.");
}
}
static private void buzzLoop()
{
while (true)
{
//simulate something error prone, like some risky IO
System.Threading.Thread.Sleep(200);
bool isErr = (new Random().Next(1, 100) == 10);
if (isErr)
throw new Exception("Buzz got an exception.");
}
}
}
}
This might be one of the rare cases when an async void method could be convenient:
static async void StartAndMonitorAsync(Func<Task> taskFunc)
{
while (true)
{
var task = taskFunc();
try
{
await task;
// process the result if needed
return;
}
catch (Exception ex)
{
// log the error
System.Console.WriteLine("Error: {0}, restarting...", ex.Message);
}
// do other stuff before restarting (if any)
}
}
static private void startLoops()
{
System.Console.WriteLine("Starting fizzLoop.");
StartAndMonitorAsync(() => Task.Factory.StartNew(new Action(fizzLoop)));
System.Console.WriteLine("Starting buzzLoop.");
StartAndMonitorAsync(() => Task.Factory.StartNew(new Action(buzzLoop)));
}
If you can't use async/await, a similar logic can be implemented using Task.ContinueWith.
If startLoops can be called multiple times (while tasks are already "in-flight"), you'd need to add cancellation logic to StartAndMonitorAsync and the tasks it sarts, using CancelltionToken (more details in "A pattern for self-cancelling and restarting task").
From MSDN
"The Task infrastructure wraps them in an AggregateException instance. The AggregateException has an InnerExceptions property that can be enumerated to examine all the original exceptions that were thrown, and handle (or not handle) each one individually. Even if only one exception is thrown, it is still wrapped in an AggregateException."
For more information you can check this
try
{
System.Console.WriteLine("Starting fizzLoop.");
var fizzTask = Task.Factory.StartNew(new Action(fizzLoop));
System.Console.WriteLine("Starting buzzLoop.");
var buzzTask = Task.Factory.StartNew(new Action(buzzLoop));
}
catch (AggregateException ae)
{
// Assume we know what's going on with this particular exception.
// Rethrow anything else. AggregateException.Handle provides
// another way to express this. See later example.
foreach (var e in ae.InnerExceptions)
{
if (e is MyCustomException)
{
Console.WriteLine(e.Message);
}
else
{
throw;
}
}
}

Can I write a C# method that will terminate execution of anyone who calls it (within the same class)?

I have a C# class that is typically executed in a thread. The caller can call a .Cancel method to stop the execution of the thread.
The ".Cancel" method will set a boolean "Cancelled" property to "True". The actual cancellation comes from little blocks like this, scattered all over the place in my code:
public void ThisGetsExecutedAsAThread()
{
.....
DoThing1;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
DoThing2;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
DoThing3;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
.....
}
This approach works quite well (i.e., the caller can cancel the action, and the execution stops within a few seconds), but as you can see it is quite repetitive.
I'd like to replace those blocks with something more like this:
...Do some action...
TerminateIfCancelled;
...Do some action....
Is it possible to define a "TerminateIfCancelled" that will cause the caller to return?
Or have I missed some much better general solution to this problem..?
Best way to end a thread is return from its function, and there are only 2 ways of returning from a function - return and throw, so if you don't like if(Cancelled) return; you can define new exception type (CancelledException for example) and throw it in your TerminateIfCancelled:
sealed class CancelledException : Exception { }
private void TerminateIfCancelled()
{
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
throw new CancelledException();
}
}
public void ThisGetsExecutedAsAThread()
{
try
{
DoThing1;
TerminateIfCancelled();
DoThing2;
TerminateIfCancelled();
DoThing3;
TerminateIfCancelled();
}
catch(CancelledException)
{
return;
}
}
C# will help you with cancel/error/continue actions if you use Task or Task<T>
Get the thread instance that you created and abort it from another thread:
Thread oThread = new Thread(new ThreadStart(someDelegate));
oThread.Start()
and on your "CancelButton_Click":
oThread.Abort()
It will raise a ThreadAbortedException on the Thread. You should catch that exception and fail gracefully.

Set timeout to an operation

I have object obj which is 3rd party component,
// this could take more than 30 seconds
int result = obj.PerformInitTransaction();
I don't know what is happening inside.
What I know is if it take longer time, it is failed.
how to setup a timeout mechanism to this operation, so that if it takes more than 30 seconds I just throw MoreThan30SecondsException ?
You could run the operation in a separate thread and then put a timeout on the thread join operation:
using System.Threading;
class Program {
static void DoSomething() {
try {
// your call here...
obj.PerformInitTransaction();
} catch (ThreadAbortException) {
// cleanup code, if needed...
}
}
public static void Main(params string[] args) {
Thread t = new Thread(DoSomething);
t.Start();
if (!t.Join(TimeSpan.FromSeconds(30))) {
t.Abort();
throw new Exception("More than 30 secs.");
}
}
}
More simply using Task.Wait(TimeSpan):
using System.Threading.Tasks;
var task = Task.Run(() => obj.PerformInitTransaction());
if (task.Wait(TimeSpan.FromSeconds(30)))
return task.Result;
else
throw new Exception("Timed out");
If you don't want to block the main thread you can use a System.Threading.Timer:
private Thread _thread;
void Main(string[] args)
{
_thread = new ThreadStart(ThreadEntry);
_thread.Start();
Timer timer = new Timer(Timeout,null,30000,Timeout.Infinite);
}
void ThreadEntry()
{
int result = obj.PerformInitTransaction();
}
void TimeOut(object state)
{
// Abort the thread - see the comments
_thread.Abort();
throw new ItTimedOutException();
}
Jon Skeet has a less forceful way (Shutting Down Worker Threads Gracefully) of stopping the thread than abort.
However as you're not in control of the operations PerformInitTransaction() is doing there is not much you can do from when Abort fails and leaves the object in an invalid state. As mentioned if you are able to cleanup anything that aborting the PerformInitTransaction has left hanging, you can do this by catching the ThreadAbortException, though as it's a 3rd party call it'll mean guessing the state you've left their method in.
The PerformInitTransaction should really be the one providing the timeout.
The following are two implementations which also throw any exception that happens in the internal task.
For actions (no return value):
public static bool DoWithTimeout(Action action, int timeout)
{
Exception ex = null;
CancellationTokenSource cts = new CancellationTokenSource();
Task task = Task.Run(() =>
{
try
{
using (cts.Token.Register(Thread.CurrentThread.Abort))
{
action();
}
}
catch (Exception e)
{
if (!(e is ThreadAbortException))
ex = e;
}
}, cts.Token);
bool done = task.Wait(timeout);
if (ex != null)
throw ex;
if (!done)
cts.Cancel();
return done;
}
For Funcs (with return value):
public static bool DoWithTimeout<T>(Func<T> func, int timeout, out T result)
{
Exception ex = null;
result = default(T);
T res = default(T);
CancellationTokenSource cts = new CancellationTokenSource();
Task task = Task.Run(() =>
{
try
{
using (cts.Token.Register(Thread.CurrentThread.Abort))
{
res = func();
}
}
catch (Exception e)
{
if (!(e is ThreadAbortException))
ex = e;
}
}, cts.Token);
bool done = task.Wait(timeout);
if (ex != null)
throw ex;
if (done)
result = res;
else
cts.Cancel();
return done;
}
I think this is simplest of all:
using System.Threading.Tasks;
var timeToWait = 30000; //ms
Task.Run(async () =>
{
await Task.Delay(timeToWait);
//do your timed task i.e. --
int result = obj.PerformInitTransaction();
});
You need to be careful about aborting an operation like this, especially as it's in a 3rd party component that you (possibly) don't have access to the code to modify.
If you abort the operation then you won't know what state you've left the underlying class in. For example, it may have acquired a lock, and your about has caused that lock to not be released. Even if you destroy the object after aborting the operation it may have altered some state that is global to it and therefore you won't be able to reliably create a new instance without a restart.
You might look at invoking the method in a thread and upon the timeout, abort the thread and raise the exception. Also, you shall have to handle the ThreadBorted Exception in this case.
New approach in .NET 6 / C# 10:
var task = Task.Run(() => SomeMethod(input));
return await task.WaitAsync(TimeSpan.FromSeconds(30));
There is a nice example of a generic solution to this using a helper class here.
It uses the Action delegate to avoid the Thread creation/destruction shown in the previous example.
I hope this helps.
this is what I would use. works similar to how a javascript timeout works.
public class Toolz {
public static System.Threading.Tasks.Task<object> SetTimeout(Func<object> func, int secs) {
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(secs));
return System.Threading.Tasks.Task.Run(() => func());
}
}
class Program {
static void Main(string[] args) {
Console.WriteLine(DateTime.Now);
Toolz.SetTimeout(() => {
Console.WriteLine(DateTime.Now);
return "";
}, 10);
}
}
I just ran into this in a .NET 4.0 app (no access to Task.Run, Task.Delay, etc.). If you will excuse the last line (which is the setTimeout part) it's fairly concise.
int sleepTime = 10000;
Action myAction = () => {
// my awesome cross-thread update code
this.BackColor = Color.Red;
};
new System.Threading.Thread(() => { System.Threading.Thread.Sleep(sleepTime); if (InvokeRequired) myAction(); else myAction(); }).Start();

Categories