Pausing within a MVC controller action - c#

A colleague of mine wrote some code that essentially pauses for 1 second before making a webservice call to check the state of a value. This code is written in a controller action of a MVC 4 application. The action itself is not asynchronous.
var end = DateTime.Now.AddSeconds(25);
var tLocation = genHelper.GetLocation(tid);
while (!tLocation.IsFinished && DateTime.Compare(end, DateTime.Now) > 0)
{
var t = DateTime.Now.AddSeconds(1);
while (DateTime.Compare(t, DateTime.Now) > 0) continue;
// Make the webservice call so we can update the object which we are checking the status on
tLocation = genHelper.GetLocation(tid);
}
It appears to work but for some reason I have some concerns over it's implementation. Is there a better way to make this delay?
NOTE:
We are not using .NET 4.5 and will not change to this in this solution
Javascript scrip options like SignalR are not an option at present
I had thought the question was a good option but he did not take it up and said it wasn't required as what he did works.
How to put a task to sleep (or delay) in C# 4.0?

For MVC and your situation, this is sufficient:
System.Threading.Thread.Sleep( 1000 );
A fancy way to do the same thing but with more overhead:
Task.WaitAll( Task.Delay( 1000 ) );
Update:
Quick and dirty performance test:
class Program
{
static void Main()
{
DateTime now = DateTime.Now;
for( int i = 0; i < 10; ++i )
{
Task.WaitAll( Task.Delay( 1000 ) );
}
// result: 10012.57xx - 10013.57xx ms
Console.WriteLine( DateTime.Now.Subtract( now ).TotalMilliseconds );
now = DateTime.Now;
for( int i = 0; i < 10; ++i )
{
Thread.Sleep( 1000 );
}
// result: *always* 10001.57xx
Console.WriteLine( DateTime.Now.Subtract( now ).TotalMilliseconds );
Console.ReadLine();
}
}

Related

Why is C# Threading not woking on multiple cores?

my code is a bit complex, but the core is starting threads like this:
Thread task = new Thread(new ParameterizedThreadStart(x => { ThreadReturn = BuildChildNodes(x); }));
task.Start((NodeParameters)tasks[0]);
it should work. but when i check my CPU usage i get barely 10%. so i do assume it's just using one core. barely.
ThreadReturn btw is a value i use a setter on, to have some kind of event, when the thread is ready:
public object ThreadReturn
{
set
{
lock (thisLock)
{
NodeReturn result = (NodeReturn)value;
if (result.states.Count == 0) return;
Content[result.level + 1].AddRange(result.states);
if (result.level + 1 >= MaxDepth) return;
for (int i = 0; i < result.states.Count; i++)
{
Thread newTask = new Thread(new ParameterizedThreadStart(x => ThreadReturn = BuildChildNodes(x)));
NodeParameters param = new NodeParameters()
{
level = result.level + 1,
node = Content[result.level + 1].Count - (i + 1),
turn = SkipOpponent ? StartTurn : !result.turn
};
if (tasks.Count > 100)
unstarted.Add(param);
else
{
newTask.Start(param);
tasks.Add(newTask);
}
}
}
}
}
i got some crazy error about mark stack overflow so i limited the maximum number of parallel tasks with putting them into a second list...
i'm not firm in multithreading so this code is a little bit messy... maybe you can show me a better way which actually uses my cores.
btw: it's not the locks fault. i tried without before. -> same result
Edit: this is my code before i went to the Threading class. i find it more suitable:
Content.Clear();
Content.Add(new List<T> { Root });
for (var i = 0; i < maxDepth; i++)
Content.Add(new List<T>());
Task<object> firstTask = new Task<object>(x => BuildChildNodes(x), (new NodeParameters() { level = 0, node = 0, turn = Turn }));
firstTask.Start();
tasks.Add(firstTask);
while (tasks.Count > 0 && Content.Last().Count == 0)
{
Task.WaitAny(tasks.ToArray());
for (int task = tasks.Count - 1; task >= 0; task--)
{
if (tasks[task].IsCompleted)
{
NodeReturn result = (NodeReturn)tasks[task].Result;
tasks.RemoveAt(task);
Content[result.level + 1].AddRange(result.states);
if (result.level + 1 >= maxDepth) continue;
for (int i = 0; i < result.states.Count; i++)
{
Task<object> newTask = new Task<object>(x => BuildChildNodes(x), (object)new NodeParameters() { level = result.level + 1, node = Content[result.level + 1].Count - (i + 1), turn = SkipOpponent ? Turn : !result.turn });
newTask.Start();
}
}
}
}
In every state i'm calculating children and in my main thread i put them into my state tree while waiting for the tasks to finish. please assume i'd actually use the return value of waitany, i did a git reset and now... welll... it's gone^^
Edit:
Okay i don't know what exactly i did wrong but... in general everything was a total mess. i now implemented the deep construction method and maybe because there's much less... "traffic" now my whole code runs in 200ms. so... thanks for this!
i don't know if i should delete this question hence stupidity or if you guys want to post answers so i can rate them postive, you really helped me a lot :)
Disregarding all the other issues you have here, essentially your lock ruins the show.
What you are saying is, hey random person go and do some stuff! just make sure you don't do it at the same time as anyone else (lock), you could have 1000 threads, but only one thread is going to be active at one time on one core, hence your results.
Here are some other thoughts.
Get the gunk out of the setter, this would fail any sane code review.
Use Tasks instead of Thread.
Thinking about what needs thread safety, and elegantly lock only what needs it, Take a look at the Interlocked for dealing with numeric atomic manipulation
Take a look at the concurrent collections you may get more mileage out of this
Simplify your code.
I can't give any more advice as it's just about impossible to know what you are trying to do.

How do I run a method while a timer is running on screen?

First off- this is a homework assignment. I'm supposed to go beyond what we have learned, so I thought of a WPM console application.
I did a lot of searching on Timers, but that's way too over my head for first semester.
So I found an easier way. The thing is, I want to be able to call some string and have the user type them in, and run a calculation in the end to determine their words per minute. I read that using Task.Factory.StartNew should let me run two methods.
class Program
{
static void Main( string[] args )
{
Timer go = new Timer( );
WordBank display = new WordBank( );
Task.Factory.StartNew(go.timer1_Tick);
Task.Factory.StartNew(display.LevelOneWords);
Console.ReadKey( );
}
}//end main
class Timer
{
public Timer()
{}
public void timer1_Tick( )
{
int seconds= 0;
DateTime dt = new DateTime( );
do
{
Console.Write("One minute timer: " + dt.AddSeconds(seconds).ToString("ss"));
Console.Write("\r");
seconds++;
Thread.Sleep(1000);
} while ( seconds< 60 );
}
}//end Timer
class WordBank
{
public WordBank()
{ }
public void LevelOneWords()
{
string easyWords = "the boy had so much fun at the park.";
Console.WriteLine("\n\n", easyWords);
Console.ReadKey( );
}
When I run the program the timer starts for a second and then is immediately replaced with the string. Am I using Task.Factory.StartNew incorrectly?
Instead of running a timer while they are typing (requiring two programs simultaneously), instead try getting the time when they initially start typing, the time when they end typing, and then do some division. IE:
static void Main()
{
// Displays WordBank
WordBank display = new WordBank();
var startTime = DateTime.Now;
// Let them type for X amount of time
var totalWords = TakeUserInputForXSeconds(45);
var endTime = DateTime.Now;
var wpm = totalWords / (endTime.Subtract(startTime).TotalMinutes);
}
For the TakeUserInputForXSeconds method, I would look at the information in this post: Stop running the code after 15 seconds

Can I stop a System.Threading.Timer

I have an application that uses timers to occasionally run monitoring tasks on secondary threads. Some of these cleanup tasks take a lot of time and I would like to be able to abort these tasks (gracefully if possible) when my user ends the program.
Is there any way to abort the thread programatically as I can with Thread.Abort(), or would I have to add a flag to the code to indicate that the thread has finished and check for that in valrious places in the code that is started by the timer?
You can stop the timer before it's callback executes using .change, but once the callback starts executing you should use an application level flag to allow your code to exit.
As a side note, you shouldn't use thread.abort() unless you are absolutely 100% sure that you know the state it is going to be left in. it can seriously destabilize your application in strange ways.
There is no way to know the Thread on which a Threading.Timer callback will run ahead of time. Hence there is no general way to abort it. It is possible to have the callback itself communicate the Thread instance but it opens up a couple of race conditions
Note: In general using Abort is a bad practice. It's a fairly reliable way to end up with hard to detect deadlocks and / or resource leaks. It's much better to use a passive mechanism like CancellationToken
use this.Timer.Change(Timeout.Infinite, Timeout.Infinite);
first i have use .dispose method but it does not work in my case so i have use Timer.change.
this is the best solution i have find.
You mean something along these lines?
using System;
using System.Threading ;
class AppCore : IDisposable
{
Timer TimerInstance ;
string[] Args ;
public AppCore( string[] args )
{
if ( args == null ) throw new ArgumentNullException("args") ;
this.TimerInstance = new Timer( Tick , null , new TimeSpan(0,0,30) , new TimeSpan(0,0,15) ) ;
this.Args = args ;
this.Cancelled = false ;
this.Disposed = false ;
return ;
}
public int Run()
{
// do something useful
return 0 ;
}
private bool Cancelled ;
public void Cancel()
{
lock( TimerInstance )
{
Cancelled = true ;
TimerInstance.Change( System.Threading.Timeout.Infinite , System.Threading.Timeout.Infinite ) ;
}
return ;
}
private void Tick( object state )
{
if ( !Cancelled )
{
// do something on each tick
}
return ;
}
private bool Disposed ;
public void Dispose()
{
lock ( TimerInstance )
{
if ( !Disposed )
{
using ( WaitHandle handle = new EventWaitHandle( false , EventResetMode.ManualReset ) )
{
TimerInstance.Dispose( handle ) ;
handle.WaitOne() ;
}
Disposed = true ;
}
}
return ;
}
}
public void stopTimer(){
myThreadingTimer = null;
}
Explication: Destroy object = destroy proccess.

C# Passed state object to Task gets changed

I'm fighting with this for days, I hope You can push me in the right direction.
This is a recursive threading algorithm which parses a resource in a thread looking for links to other resources storing them in a ConcurrentBag for future TakeOuts. Threads creation is limited by an array with configurable size to preserve resources.
I have a private static ConcurrentBag<string> which gets filled by many threads. These are Tasks that are stored in private static Task[] with configurable size (app preferences).
There is a loop in Main that's doing TryTake() into local string url variable. When successfull it loops the Task[] trying to find empty slot creating new Task passing state object url and storing it in Task[] like this:
TaskArray[x] = new Task(FindLinks, url, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
The FindLinks is declared as
private static readonly Action<object> FindLinks = input => { ... }
In the main Task[] loop I am setting url to null before next TryTake(out url).
What is my problem here is the state object input that is passed from url in the main loop becomes null inside the Task lambda function. I've read almost all MSDN articles about TPL and can't figure this one out :(
How can I pass a variable (string) to the Task safely without closure (or whatever it is happening).
Any other ideas about improving this algorithm are welcome too.
Thanks.
Edit:
I have solved the problem by reordering statements and slightly rewriting the code in the main loop. No more assigning null to the variable. I suspect it was caused by compiler's statement reordering or preemption. Here is what it looks like now causing no more troubles:
string url;
if (CollectedLinks.TryTake(out url))
{
var queued = false;
while (!queued)
{
// Loops thru the array looking for empty slot (null)
for (byte i = 0; i < TaskArray.Length; i++)
{
if (TaskArray[i] == null)
{
TaskArray[i] = new Task(FindLinks, url, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
TaskArray[i].Start(TaskScheduler.Current);
queued = true; break;
}
}
if (!queued)
{
// Loop and clean the array
for (var i = 0; i < TaskArray.Length; i++)
{
if (TaskArray[i] == null)
continue;
if (TaskArray[i].Status == TaskStatus.RanToCompletion || TaskArray[i].Status == TaskStatus.Canceled || TaskArray[i].Status == TaskStatus.Faulted)
{
TaskArray[i].Wait(0);
TaskArray[i] = null;
}
}
}
}
}
I have solved the problem by reordering statements and slightly rewriting the code in the main loop. No more assigning null to the variable. I suspect it was caused by compiler's statement reordering or preemption. Here is what it looks like now causing no more troubles:
string url;
if (CollectedLinks.TryTake(out url))
{
var queued = false;
while (!queued)
{
// Loops thru the array looking for empty slot (null)
for (byte i = 0; i < TaskArray.Length; i++)
{
if (TaskArray[i] == null)
{
TaskArray[i] = new Task(FindLinks, url, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
TaskArray[i].Start(TaskScheduler.Current);
queued = true; break;
}
}
if (!queued)
{
// Loop and clean the array
for (var i = 0; i < TaskArray.Length; i++)
{
if (TaskArray[i] == null)
continue;
if (TaskArray[i].Status == TaskStatus.RanToCompletion || TaskArray[i].Status == TaskStatus.Canceled || TaskArray[i].Status == TaskStatus.Faulted)
{
TaskArray[i].Wait(0);
TaskArray[i] = null;
}
}
}
}
}

C#: Is it possible to cancel a linq2sql query?

Is it possible to cancel a linq2sql query? Like if I have built a query that takes a while to run, I would like it to be possible for the user to cancel it. Does anyone have any good ideas on this?
If you set the CommandTimeout (seconds) property of DataContext, it will automatically throw an exception after the timeout elapses.
So, according to Richard Szalay's comment:
Your best bet is to run the query in a background thread and simply unsubscribe from the container object's events when the user hits Cancel.
And I think I agree that this is a an ok work-around for now. What I would love to see is some Async query functionality already in the framework, but until that happens this will have to do.
Haven't started to implement this yet (have to finish some other things first), but one way it could work:
In the working thread, do the queries in a separate query thread and then Join that thread until it is finished.
When user hits cancel, call the Interrupt method of the working thread, which would then get an ThreadInterruptedException and stop waiting for the query thread to finish.
May add some code later when I make it. But we'll see how pretty it turns out :p
I know this answer is kind of late but this is how I do it:
class Program
{
public class Person
{
public string Name;
public int Age;
}
public static void ExecuteQueryAsync ( IEnumerable<Person> collectionToQuery , Action<List<Person>> onQueryTerminated , out Action stopExecutionOfQuery )
{
var abort = false;
stopExecutionOfQuery = () =>
{
abort = true;
};
Task.Factory.StartNew( () =>
{
try
{
var query = collectionToQuery.Where( x =>
{
if ( abort )
throw new NotImplementedException( "Query aborted" );
// query logic:
if ( x.Age < 25 )
return true;
return
false;
} );
onQueryTerminated( query.ToList() );
}
catch
{
onQueryTerminated( null );
}
});
}
static void Main ( string[] args )
{
Random random = new Random();
Person[] people = new Person[ 1000000 ];
// populate array
for ( var i = 0 ; i < people.Length ; i++ )
people[ i ] = new Person() { Age = random.Next( 0 , 100 ) };
Action abortQuery;
ExecuteQueryAsync( people , OnQueryDone , out abortQuery );
// if after some time user wants to stop query:
abortQuery();
Console.Read();
}
static void OnQueryDone ( List<Person> results )
{
if ( results == null )
Console.WriteLine( "Query was canceled by the user" );
else
Console.WriteLine( "Query yield " + results.Count + " results" );
}
}
I'd say you'd probably need to run it on a separate Thread and cancel that instead.

Categories

Resources