i have a specific state(business case),i want to check it every period of time,to execute an action..they tell me to write a patch to handle this situation ..
the application i works in is a web application (asp.net)..
i don't know how to write the patch ,, and i don't know if the patch is the ideal solution in this state or not..
please any suggestions ,, any details explanation for this issue..
thanks in advance.
Firstly, it is quite simple to setup a timer to do this check. Initialise a timer,
int _State;
System.Timers.Timer stateCheckTimer = new System.Timers.Timer();
stateCheckTimer.Interval = 1000; // TODO - set to desired interval (in ms)
stateCheckTimer.AutoReset = true;
stateCheckTimer.Elapsed += stateCheckTimer_Elapsed;
Then just check your state in the stateCheckTimer_Elapsed function,
void stateCheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// Check for the desired state
if (_State == 1)
{
// Do something
}
}
The most difficult thing will be accessing the _State, so you'll probably have to put the timer in the same location as it (or have it passed, whatever works). I would suggest an event driven solution though. Make a public event handler on your class that handles the state,
public EventHandler OnStateChanged;
Then, encapsulate the access to your state variable (in this example, _State) so that you control the setting of it. When it is set, fire off this event. I do this through a property,
public int State
{
get { return _State; }
set
{
_State = value;
if (OnStateChanged != null)
{
OnStateChanged(this, null);
}
}
}
Then, you just need to wire up an event handle to execute your desired action,
OnStateChanged += StateChangeAction;
And in that function execute your desired action,
void StateChangeAction(object sender, EventArgs args)
{
// Check for the desired state
if (_State == 1)
{
// Do something
}
}
(you will have to pass the state in through the EventArgs args but that is pretty simple to do). This way, whenever the state changes you will immediately be able to act upon it (send an email, do whatever it is) rather than having to poll the state every x seconds or minutes. It will use less resources, be more reactive (quicker), and ultimately be neater code! If you are able to do it this way, I would highly recommend it.
this checking is done from the browser or on the server side application ?
if it is done from the client( Browser ) than you can do it with JavaScript See this Post
If you want to do it from the Server Side code than , you can do it with a thread, make thread sleep for some time and when it's wake up than check the state of your object
Is the action to be executed a database one, e.g. update some row in the database? If yes you can create a database job that handles this situation.
What about writing a small simple service that works in the background 24/7. I think its the simplest solution.
Related
Consider I am having a button called "Add" and is bind with the command "AddBtnExceuteCommand".
Consider Execute() method of this Command having very large and time consuming calculations.
I am developing a tool which will save the Actions like Click, Entering text into textbox etc. When I play it back the same actions will executed automatically.
consider I started recording actions. Lets say I have Clicked on Button called "Add". this click actions will save in some file called "Actions.xml". When I Started playing back that saved action by reading "Actions.xml" file. I have only Control over the Button not on the code behind of that button(means I do not have access to the AddBtnExceuteCommand command).
My Actions.Xml have lot of such actions which will be executed serially.
What I want===>
When I started Reading Actions.xml that will execute saved Actions(Clicks) automatically without considering whether the Code behind of button is executed or not. I want to Restrict the execution of second action unless The code behind of first Button is executed. So to do that I need to know whether the Code behind for that button click is executed or not. I am not having access to the code behind. I have controls(this is not wpf Controls) on Button.
I have Used White TestStack framework to get the control of Windows controls(like Button)
My UI may be Responsive while button click method performing lengthy calculations. UI might be on different thread.
So is it possible to check whether the code behind for that button click is executed or not. I wanted to check it only from button control.
Thanks.
Basically you are telling you having two logics:
Logic for the click
Logic for "enabling" the button
I guess you need to use a RelayCommand from the GalaSoft.MvvmLight.Command (please check this URL on how to install and this one on how use it).
Basically, you just bind your command in the view:
<Button Command="{Binding StoreActionCommand}"/>
And in the ViewModel ("code behind"), you specify two different actions: one is what the button do, and the next one is if this code can be executed.
You need to add this to the constructor of your ViewModel:
// declare your public attribute (it can be a property too if you want)
public ICommand StoreActionCommand;
// and on your ViewModel constructor
StoreActionCommand = new RelayCommand(StoreCommandExecute, CanStoreCommand);
private void StoreCommandExecute()
{
// here you add actions to your queue
}
private bool CanStoreCommand()
{
// here, you can check if your queue is empty or not..
return true;
}
If you want to add items, do you need to store it on an XML? Could it be just memory based? You could use a Queue for it.
For the background Thread, I would advise you to start working with the Task library. Besides being easier to understand, it is easier to control it. And never from your background thread try to interact with the UI. you can do it with some thread synchronization, but I would not recommend it. If you are doing something in the background, let it only do something and then return. Otherwise, use the IProgress classes to notify changes in the UI.
EDIT
I still note sure if that's what your looking for, but I'll try to help you again.
I usually do that do notify the UI when I have to do a background task notifying changes to the UI. You can use the IProgress to change some properties that are used by your UI. Note that you do not change the UI directly.. never! You just need to make a set of properties that do that for you.
First, create some properties so that your UI can connect to them:
private string executionStatus = string.Empty;
public string ExecutionStatus
{
get { return executionStatus; }
set
{
executionStatus = value;
RaisePropertyChanged(nameof(ExecutionStatus));
}
}
private bool canRun = true;
public bool CanRun
{
get { return canRun; }
set
{
canRun = value;
RaisePropertyChanged(nameof(CanRun));
}
}
Then, change the StoreActionCommand and CanStoreCommand to something like:
private bool CanStoreCommand()
{
return CanRun;
}
// note the async here
private async void StoreActionCommand()
{
CanRun = false;
// notification
var progressNotification = new Progress<string>((value) => ExecutionStatus = value);
// real background thread goes here, without blocking the UI
await Task.Run(() => {
DoWork(progressNotification);
});
CanRun = True;
}
private void DoWork(IProgress<string> progress)
{
progress.Report("Starting...");
try
{
progress.Report("doing x...");
progress.Report("doing y...");
}
catch(Exception err)
{
progress.Report(err);
}
progress.Report("Process finished");
}
Hope this helps you.
If you have to work on more items, you could control the CanRun as you want.
Another interesting stuff is that you could create a Model class in order to send more than just a string (you can pass a status and a flag indicating the possibility of the user to click the CanRun button during the work, but then a new Thread would be fired in parallel do the one that is already running).
I need to implement the following: I have a page on which user enters an email. Every time text changes, I have to check whether the user exists in a DB and based on that information, I should set the text of the button to either "Sign up" or "Sign in". The problem is, that this DB request may take a couple of seconds (the reason is irrelevant) and the API is async, so event handler will be decorated with async, and since mail entry may change several times, this handler will be called several times before any one will end. So I'll have concurrent API requests and then, potentially, concurrent attempts to change the button text and that may not end well. I thought of something like this:
private async void OnTextChanged(object sender, TextChangedEventArgs e)
{
mailEntry.TextChanged -= OnTextChanged;
...
submitButton.Text = (await api.AccountExistAsync(mailEntry.Text)).IsRegistered
? "Sign in"
: "Sign up";
...
mailEntry.TextChanged += OnTextChanged;
}
But a problem with this design, is that, say, a valid email was entered between -= OnTextChanged and += OnTextChanged, in which case it'll never be checked.
My question is, what is the right way to implement what I'm trying to achieve? Thanks in advance.
Here is one solution:
private long requestNumber;
private async void OnTextChanged(object sender, TextChangedEventArgs e)
{
var text = mailEntry.Text;
long myRequestNumber = ++requestNumber;
await Task.Delay(200);
if (requestNumber != myRequestNumber)
return;
var result = (await api.AccountExistAsync(text)).IsRegistered;
if (requestNumber != myRequestNumber)
return;
submitButton.Text = result ? "Sign in" : "Sign up";
}
It maintains a requestNumber variable to hold the last request number which is incremented each time you change the text.
If after the AccountExistAsync operation completes the code discovers that the variable was changed, it will conclude that a new request has been issued, and will not update the UI.
Please note that the solution also waits 200 milliseconds before attempting to send a validation request. Although this will delay the validation operation 200 milliseconds, it will prevent too many requests to be sent, especially as the user is typing quickly. This is optional of course.
Edit:
I removed the use of synchronization when reading/updating requestNumber because such code runs in the UI thread only.
I'm fairly new to C#, and recently built a small webapp using .NET 4.0. This app has 2 parts: one is designed to run permanently and will continuously fetch data from given resources on the web. The other one accesses that data upon request to analyze it. I'm struggling with the first part.
My initial approach was to set up a Timer object that would execute a fetch operation (whatever that operation is doesn't really matter here) every, say, 5 minutes. I would define that timer on Application_Start and let it live after that.
However, I recently realized that applications are created / destroyed based on user requests (from my observation they seem to be destroyed after some time of inactivity). As a consequence, my background activity will stop / resume out of my control where I would like it to run continuously, with absolutely no interruption.
So here comes my question: is that achievable in a webapp? Or do I absolutely need a separate Windows service for that kind of things?
Thanks in advance for your precious help!
Guillaume
While doing this on a web app is not ideal..it is achievable, given that the site is always up.
Here's a sample: I'm creating a Cache item in the global.asax with an expiration. When it expires, an event is fired. You can fetch your data or whatever in the OnRemove() event.
Then you can set a call to a page(preferably a very small one) that will trigger code in the Application_BeginRequest that will add back the Cache item with an expiration.
global.asax:
private const string VendorNotificationCacheKey = "VendorNotification";
private const int IntervalInMinutes = 60; //Expires after X minutes & runs tasks
protected void Application_Start(object sender, EventArgs e)
{
//Set value in cache with expiration time
CacheItemRemovedCallback callback = OnRemove;
Context.Cache.Add(VendorNotificationCacheKey, DateTime.Now, null, DateTime.Now.AddMinutes(IntervalInMinutes), TimeSpan.Zero,
CacheItemPriority.Normal, callback);
}
private void OnRemove(string key, object value, CacheItemRemovedReason reason)
{
SendVendorNotification();
//Need Access to HTTPContext so cache can be re-added, so let's call a page. Application_BeginRequest will re-add the cache.
var siteUrl = ConfigurationManager.AppSettings.Get("SiteUrl");
var client = new WebClient();
client.DownloadData(siteUrl + "default.aspx");
client.Dispose();
}
private void SendVendorNotification()
{
//Do Tasks here
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
//Re-add if it doesn't exist
if (HttpContext.Current.Request.Url.ToString().ToLower().Contains("default.aspx") &&
HttpContext.Current.Cache[VendorNotificationCacheKey] == null)
{
//ReAdd
CacheItemRemovedCallback callback = OnRemove;
Context.Cache.Add(VendorNotificationCacheKey, DateTime.Now, null, DateTime.Now.AddMinutes(IntervalInMinutes), TimeSpan.Zero,
CacheItemPriority.Normal, callback);
}
}
This works well, if your scheduled task is quick.
If it's a long running process..you definitely need to keep it out of your web app.
As long as the 1st request has started the application...this will keep firing every 60 minutes even if it has no visitors on the site.
I suggest putting it in a windows service. You avoid all the hoops mentioned above, the big one being IIS restarts. A windows service also has the following benefits:
Can automatically start when the server starts. If you are running in IIS and your server reboots, you have to wait until a request is made to start your process.
Can place this data fetching process on another machine if needed
If you end up load-balancing your website on multiple servers, you could accidentally have multiple data fetching processes causing you problems
Easier to main the code separately (single responsibility principle). Easier to maintain the code if it's just doing what it needs to do and not also trying to fool IIS.
Create a static class with a constructor, creating a timer event.
However like Steve Sloka mentioned, IIS has a timeout that you will have to manipulate to keep the site going.
using System.Runtime.Remoting.Messaging;
public static class Variables
{
static Variables()
{
m_wClass = new WorkerClass();
// creates and registers an event timer
m_flushTimer = new System.Timers.Timer(1000);
m_flushTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnFlushTimer);
m_flushTimer.Start();
}
private static void OnFlushTimer(object o, System.Timers.ElapsedEventArgs args)
{
// determine the frequency of your update
if (System.DateTime.Now - m_timer1LastUpdateTime > new System.TimeSpan(0,1,0))
{
// call your class to do the update
m_wClass.DoMyThing();
m_timer1LastUpdateTime = System.DateTime.Now;
}
}
private static readonly System.Timers.Timer m_flushTimer;
private static System.DateTime m_timer1LastUpdateTime = System.DateTime.MinValue;
private static readonly WorkerClass m_wClass;
}
public class WorkerClass
{
public delegate WorkerClass MyDelegate();
public void DoMyThing()
{
m_test = "Hi";
m_test2 = "Bye";
//create async call to do the work
MyDelegate myDel = new MyDelegate(Execute);
AsyncCallback cb = new AsyncCallback(CommandCallBack);
IAsyncResult ar = myDel.BeginInvoke(cb, null);
}
private WorkerClass Execute()
{
//do my stuff in an async call
m_test2 = "Later";
return this;
}
public void CommandCallBack(IAsyncResult ar)
{
// this is called when your task is complete
AsyncResult asyncResult = (AsyncResult)ar;
MyDelegate myDel = (MyDelegate)asyncResult.AsyncDelegate;
WorkerClass command = myDel.EndInvoke(ar);
// command is a reference to the original class that envoked the async call
// m_test will equal "Hi"
// m_test2 will equal "Later";
}
private string m_test;
private string m_test2;
}
I think you can can achieve it by using a BackgroundWorker, but i would rather suggest you to go for a service.
Your application context lives as long as your Worker Process in IIS is functioning. In IIS there's some default timeouts for when the worker process will recycle (e.g. Number of Idle mins (20), or regular intervals (1740).
That said, if you adjust those settings in IIS, you should be able to have the requests live, however, the other answers of using a Service would work as well, just a matter of how you want to implement.
I recently made a file upload functionality for uploading Access files to the database (not the best way but just a temporary fix to a longterm issue).
I solved it by creating a background thread that ran through the ProcessAccess function, and was deleted when completed.
Unless IIS has a setting in which it kills a thread after a set amount of time regardless of inactivity, you should be able to create a thread that calls a function that never ends. Don't use recursion because the amount of open functions will eventually blow up in you face, but just have a for(;;) loop 5,000,000 times so it'll keep busy :)
Application Initialization Module for IIS 7.5 does precisely this type of init work. More details on the module are available here Application Initialization Module
So I have this interface that is just one big GO button that syncs a bunch of data from one tool to another. The problem is it takes a really long freaking time and some users are left wondering whats the deal. So I am wondering if there is a way that I can put something in my loop so that every so many entries it sends something back to the page to update them on the progress.
Currently it is just an .aspx page with an aspx.cs behind it. The Go button fires off the whole process and it calls Response.Write a ton of times (as well as writing the same thing to a log file I made) but the Responses don't show until the entire thing is done.
Please advise.
You could design a class which will be stored in the session and which will represent the current state of the operation:
public class OperationState
{
public object Result { get; set; }
public int Progress { get; set; }
public string Error { get; set; }
}
An instance of this class could be created when you start the operation and store it in the user session. Then at each step of the operation you could retrieve it from session and update the progress property. Once the operation terminates you could set the Result property or the Error property in case an exception occurs. In the meantime you could design a PageMethod which will be accessible from client script. This method will simply return the State instance from the session. You will then invoke it periodically and asynchronously from javascript to check the progress and update the DOM to notify the user.
I am assuming you are calling another class to do the work. Lets call this the WorkerClass
You can have the WorkerClass have an event hooked up to it, that the .aspx page hooks up too and will write a message when the event is triggered.
// Overload EventArgs to send messageas back up
public delegate void UpdateMethod(object sender, EventArgs e);
public class WorkerClass
{
public event UpdateMethod UpdateMethod;
}
WorkerClass worker = new WorkerClass();
worker.UpdateMethod += new UpdateMethod(worker_UpdateMethod);
EDIT based on Comment it is on there page
If you don't want to refactor to another class doing the work (which I suggest). You can post the messages this way.
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
this.ProcessMassiveWorkLoad();
}
private void ProcessMassiveWorkLoad()
{
for(int i = 0; i < 100000; i++)
{
// Do some work
// Write the fact you have work
Response.Write(string.Format("Done {0} of 100000", i);
}
}
The simplest way to resolve your issue is to call Response.Flush() after each Response.Write.
This will flush the current response buffer back to the client, enabling them to see the current state of the page.
Even David's method would need this to get the responses out to the user in a timely manner.
The better solution would be along the lines of Darin's solution, which would involve some client side scripting of (say) an update panel, that you refresh with a JavaScript timer to get the latest state, but that may introduce other issues for you (needing JavaScript turned on, rewriting the long running method as something you can fire off asynchronously, etc).
If it's any consolation, I've done both in the past, and would use either again.
I have a web service with two methods:
RetrieveFirstLevelOptions() and RetrieveSecondLevelOptions(int levelOneOption).
The GUI contains two comboBoxes: FirstLevelOptionsCombo and SecondLevelOptionsCombo.
I am having trouble with creating a control flow for the initialization stage when I have to make a request to RetrieveFirstLevelOptions() and then, once the results are in, call RetrieveSecondLevelOptions(default levelOneOption = 0).
The problem is that since everything happens asynchronously I don't know what the best approach is to allow this behaviour take place once and only once, at the beginning.
An option I would love to have is to attach a second event handler to the RetieveFirstLevelOptionsCompleted event and have it remove itself after running only once. But it looks like such a behaviour is impossible to get.
Another option would be to have a boolean flag to indicate whether in Initialization phase and if it is, then the handler for RetrieveFirstLevelOptionsCompleted would execute some additional logic. However this idea makes it look like all event handlers would have to check for state information and do different things depending on the current state. This seems to be bad design because the control flow seems to be descentralized.
I want to have a centralized control flow mechanism that will make the decisions in one spot. But how can this be done when everything is executed asynchronously?
"An option I would love to have is to attach a second event handler to the RetieveFirstLevelOptionsCompleted event and have it remove itself after running only once. But it looks like such a behaviour is impossible to get."
Is there some reason this isn't working:
class Example
{
SomeWebService myService;
Example()
{
// do stuff
myService.RetrieveFirstLevelOptionsCompleted += MyHandlerMethod;
}
void MyHandlerMethod(object sender, RetrieveFirstLevelOptionsCompletedEventArgs e)
{
// do stuff
myService.RetrieveFirstLevelOptionsCompleted -= MyHandlerMethod;
// potentially attach next event handler for all subsequent calls
myService.RetrieveFirstLevelOptionsCompleted += MyHandlerMethod2;
}
}
The pattern that I usually use in a situation like this is to create a wrapper around the Async web service proxy method that accepts a callback method. The callback method then gets passed to the RetrieveFirstLevelOptionsAsync() method like so:
public void RetrieveFirstLevelOptions(Action callback)
{
client.RetrieveFirstLevelOptionsAsync(callback);
}
void client_RetrieveFirstLevelOptionsCompleted(object sender, AsyncCompletedEventArgs e)
{
var callback = e.UserState as Action;
if (callback != null)
{
callback();
}
}
So when you call RetrieveFirstLevelOptions(), you just pass the callback that you want to run only once, and you don't ever have to worry about it getting called multiple times. Presumably you'd put your call to RetrieveSecondLevelOptions() within that callback.