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.
Related
I am struggling with the concept described below:
User checks x of 5 checkboxes with type of measurements and then he clicks "RUN".
On the "RUN" OnClick() I create a Measure class object.
class Measure
{
string measure_type;
SendCommandToArduino(string nameOfMeasurement)
...
}
I need to run those selected methods IN SEQUENCE (they CANNOT run asynchronous, because they use Serial COM).
I hardcoded something like this:
void Method1()
{
measurement.SendCommandToArduino("tetnienie");
}
void Method2()
{
measurement.SendCommandToArduino("jasnosc");
}
tPomiar1 = new Thread(Method1);
tPomiar1.Start();
tPomiar1.Join();
pomiar.DrawGraphTetnien(tetnienie_Chart);
tPomiar2 = new Thread(Method2);
tPomiar2.Start();
tPomiar2.Join();
MessageBox.Show("Done all measurements!");
No surprise - it worked. But:
I still don't know how to relate number of checked checkboxes with number of methods to run in these threads. Maybe I should hardcode MethodX for all measurements and then run threads from some List list_of_threads?
Threads are overkill for this purpose ( I guess ), cause the longest measurement takes about 10 seconds... Is there any other way?
ThreadPool, Tasks, async/await ? I am totally new to multi-tasking/threading
I also tried something like this, but I didn't finish this solution, it was too hardcore:
List<Thread> list_of_threads= new List<Thread>();
List<Action> measureToDo = new List<Action>();
// link those additions with checkboxes
measureToDo.Add(Method1);
measureToDo.Add(Method2);
measureToDo.Add(Method3);
int i = 0;
foreach (Action action in measureToDo)
{
//substring this one to get method's name!
string methodName = action.Method.Name.ToString());
methodName = methodName.Substring(4,6) // limit of 9 methods here haha
}
foreach (var item in measureToDo )
{
RunThread(item.Method.Name.ToString());
}
void RunThread(Action a)
{
Thread t;
t = new Thread(new ThreadStart(a.Method.Name)).Start();
}
For a measure_type I created a '5-bit' string -> Containg "1" if the checkbox on this position was checked.
"01000" / "10011" etc.
Thank You in advance for all hints/tips! :)
Perhaps you are overcomplicating things, and a simple solution would be perfectly well.
You can use Control.Tag property and add the name (as string) of the measure to everyone of your checkboxes. Then, you can enumerate your check-boxes, see which is checked, and get a list of strings with the names of the measures you need to perform.
Then, you need a single method to execute your measures. It should enumerate the list, and have a switch to map a measure to a method:
void ExecuteMeasures(List<string> measures)
{
foreach (string measure in measures)
{
switch (measure)
{
case "Measure 1": MeasureMethodOne(); break;
// and so on...
}
}
}
Then you don't need to run each measure method in a separate thread, because you want them to be executed sequentially. You only need to run the ExecuteMeasureMethod in a separate thread. Having it run for seconds, a separate thread is fine. Still, to keep things neat, use a long running task:
var listOfMeasures = new List<string>();
//Populate your list from the selection of check boxes
Task t = Task.StartNew ( ()=> ExecuteMeasures(listOfMeasures), TaskCreationOptions.LongRunning);
await t;
Here is my solution:
1. Define a Action array to store your methods
2. Get the values of checked items(checkbox1's value is 0, etc.) as the array indices
3. Invoke the relevant method in the array.
Codes are something like :
public static void Main()
{
Action[] actions = new Action[5];
actions[0] = Method1;
actions[1] = Method2;
string checkedValue = "1";
actions[int.Parse(checkedValue) - 1].Invoke();
}
static void Method1()
{
Console.WriteLine(1);
}
static void Method2()
{ }
Or you can simplify the code as below:
public static void Main()
{
Action[] actions = new Action[5];
actions[0] = ()=> { Console.WriteLine(1); };
actions[1] = ()=> { Console.WriteLine(2); };
string checkedValue = "1";
actions[int.Parse(checkedValue) - 1].Invoke();
}
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
I used the following approach long time (approx 5 years):
Create one big class with initialization of XXXEntities in controller and create each method for each action with DB. Example:
public class DBRepository
{
private MyEntities _dbContext;
public DBRepository()
{
_dbContext = new MyEntities();
}
public NewsItem NewsItem(int ID)
{
var q = from i in _dbContext.News where i.ID == ID select new NewsItem() { ID = i.ID, FullText = i.FullText, Time = i.Time, Topic = i.Topic };
return q.FirstOrDefault();
}
public List<Screenshot> LastPublicScreenshots()
{
var q = from i in _dbContext.Screenshots where i.isPublic == true && i.ScreenshotStatus.Status == ScreenshotStatusKeys.LIVE orderby i.dateTimeServer descending select i;
return q.Take(5).ToList();
}
public void SetPublicScreenshot(string filename, bool val)
{
var screenshot = Get<Screenshot>(p => p.filename == filename);
if (screenshot != null)
{
screenshot.isPublic = val;
_dbContext.SaveChanges();
}
}
public void SomeMethod()
{
SomeEntity1 s1 = new SomeEntity1() { field1="fff", field2="aaa" };
_dbContext.SomeEntity1.Add(s1);
SomeEntity2 s2 = new SomeEntity2() { SE1 = s1 };
_dbContext.SomeEntity1.Add(s2);
_dbContext.SaveChanges();
}
And some external code create DBRepository object and call methods.
It worked fine. But now Async operations came in. So, if I use code like
public async void AddStatSimplePageAsync(string IPAddress, string login, string txt)
{
DateTime dateAdded2MinsAgo = DateTime.Now.AddMinutes(-2);
if ((from i in _dbContext.StatSimplePages where i.page == txt && i.dateAdded > dateAdded2MinsAgo select i).Count() == 0)
{
StatSimplePage item = new StatSimplePage() { IPAddress = IPAddress, login = login, page = txt, dateAdded = DateTime.Now };
_dbContext.StatSimplePages.Add(item);
await _dbContext.SaveChangesAsync();
}
}
can be a situation, when next code will be executed before SaveChanged completed and one more entity will be added to _dbContext, which should not be saved before some actions. For example, some code:
DBRepository _rep = new DBRepository();
_rep.AddStatSimplePageAsync("A", "b", "c");
_rep.SomeMethod();
I worry, that SaveChanged will be called after line
_dbContext.SomeEntity1.Add(s1);
but before
_dbContext.SomeEntity2.Add(s2);
(i.e. these 2 actions is atomic operation)
Am I right? My approach is wrong now? Which approach should be used?
PS. As I understand, will be the following stack:
1. calling AddStatSimplePageAsync
2. start calling await _dbContext.SaveChangesAsync(); inside AddStatSimplePageAsync
3. start calling SomeMethod(), _dbContext.SaveChangesAsync() in AddStatSimplePageAsync is executing in another (child) thread.
4. complete _dbContext.SaveChangesAsync() in child thread. Main thread is executing something in SomeMethod()
Ok this time I (think)'ve got your problem.
At first, it's weird that you have two separate calls to SaveChangesmethod. Usually you should try to have it at the end of all your operations and then dispose it.
Even thought yes, your concerns are right, but some clarifications are needed here.
When encountering an asyncor await do not think about threads, but about tasks, that are two different concepts.
Have a read to this great article. There is an image that will practically explain you everything.
To say that in few words, if you do not await an async method, you can have the risk that your subsequent operation could "harm" the execution of the first one. To solve it, simply await it.
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();
}
}
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.