I have a method in a class that returns the data as List.I need to use timer event for this method to execute in different intervals to check the data.And I need to get the return object from the first method to another method.And I have to call the second method from the Main mehtod in console application.
public class clsSample
{
private static List<string> GetData()
{
data = clsApp.LoadData();
return data;
}
public static void InitTimer()
{
Timer t = new Timer();
t.Elapsed += new ElapsedEventHandler(OnTimedEvent);
t.Interval = 50000;
t.Enabled = true;
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
GetData();
}
}
class Program
{
static void Main()
{
List<string> data = clsSample.GetData();
}
}
I need to get the return data from GetData() method .But timer need not be called in the Main method.How is this posible?
put the following on clsSample :
public delegate void EventRaiser(List<string> data);
public event EventRaiser OnDataRetrieved;
and put this on the timer method
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
if(OnDataRetrieved !=null)
{
OnDataRetrieved(GetData())
}
}
then handle the event from the program.cs class
Related
i'm learning c# and i'm trying some stuff with the System.Timers.Timer, and i'm having a problem, cause i want to make a function that receives another function so i could 'bind' it to the timer.Elapsed event. I'm trying to build something like:
public void timerElapsedMethod(my method)
{
timer.Elapsed += my method;
}
There is a way where i can do that ?
edit 1:
Guys, what i'm trying to do is, baiscally encapsulate the timer class, so i want a user to call my function passing his function as an argument.
Like:
class MyTimer
{
public static Timer timer;
public MyTimer()
{
timer = new Timer();
}
internal void *timerElapsedMeth*(Action<object, ElapsedEventArgs> method)
{
timer.Elapsed += (if i put method here i get an error);
}
}
Now imagine someone wants to use my class and wanna do something like:
class SomeUserRandomClass
{
public static MyTimer mytimer;
public SomeUserRandomClass()
{
mytimer = new MyTimer();
}
public void userRandomMethod()
{
some code...
}
myTimer.*timerElapsedMeth*(userRandomMethod);
}
Is it possible to do that ?
Thx
You can do it something like the following.
I wouldn't try to try and asign it to the event directly. But hide the event details
class MyTimer
{
private readonly Action _userAction;
private Timer timer;
public MyTimer(Action userAction)
{
_userAction = userAction;
timer = new Timer();
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
_userAction?.Invoke();
}
}
You can accomplish this using lambda expressions.
public void timerElapsedMethod(Action myMethod) {
var timer =new Timer();
timer.Elapsed += (s, e) => {
myMethod?.Invoke();
};
}
if myMethod needs parameters, you can edit the timerElapsedMethod to take parameters.
public void timerElapsedMethod(Action myMethod, int param) {
var timer =new Timer();
timer.Elapsed += (s, e) => {
myMethod?.Invoke(param);
};
}
Hope this can help.
Create an event in your wrapper class which is fired when the timer event is fired.
class MyTimer
{
// Is there a reason you want this timer to be public? Otherwise make it private.
public static Timer timer;
public event EventHandler<ElapsedEventArgs> OnTimerEvent;
public MyTimer()
{
timer = new Timer();
}
private static void OnTimedEvent(Object sender, ElapsedEventArgs e)
{
OnTimerEvent?.Invoke(this, e);
}
}
Using your timer class:
class SomeUserRandomClass
{
private static MyTimer mytimer;
public SomeUserRandomClass()
{
mytimer = new MyTimer();
myTimer += TimerEventHandler; // Register to the event
}
public void userRandomMethod()
{
some code...
}
private static void TimerEventHandler(Object sender, ElapsedEventArgs e)
{
// Handle the event
}
}
Make sure to "unregister" the event when you Dispose your SomeUserRandomClass:
myTimer -= TimerEventHandler;
forgive me if there's any typos i wrote this by hand.. i was just wondering if there's anyway i can pass a parameter to a class and change it's variable within a method of that variable.
i was thinking of passing by reference but i can't pass the variable through the Elapsed method property.. any suggestions?
public partial class MainWindow : Window
{
private CustomTimerClass _customTimer;
private int _varIWantToChange;
public MainWindow()
{
_varIWantToChange = 1;
_customTimer = new CustomTimerClass(_varIWantToChange);
}
...
}
public CustomTimerClass()
{
private System.Timers.Timer _timer;
public CustomTimerClass(int varIWantToChange)
{
_timer = new Timer();
...
_timer.Elapsed += _timer_Elapsed; //i can't pass varIwantToChange as a parameter here
}
public void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//i want to be able to change the value of the variable "_varIWantToChange" here
}
}
You could easily pass in a callback method:
class Program
{
static private CustomTimerClass _customTimer;
static private int _varIWantToChange = 1;
static public void Main()
{
_customTimer = new CustomTimerClass(changeVar);
while (_varIWantToChange == 1)
{
System.Threading.Thread.Sleep(1);
}
}
static public void changeVar(object sender, ElapsedEventArgs e)
{
_varIWantToChange++;
Console.WriteLine(_varIWantToChange);
}
}
public class CustomTimerClass
{
private System.Timers.Timer _timer;
public CustomTimerClass()
{
}
public CustomTimerClass(ElapsedEventHandler callbackMethod)
{
_timer = new Timer();
_timer.Elapsed += callbackMethod; //i can't pass varIwantToChange as a parameter here
_timer.Elapsed += _timer_Elapsed;
_timer.Interval = 500;
_timer.Start();
}
public void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
// Do timer stuff
}
}
create a public int property
make your property set _varIWantToChange and get _varIWantToChange if you need it
Any reason you are not using System.Threading.Timer instead of System.Timers.Timer? The Threading version has constructors that allow you to pass an object in the constructor that is then passed to the handler as an argument.
From MSDN: http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
I do have one checking function that will run once opening the application.
How to make it Auto Function like every 20 seconds run the function?
Main()
{
Checking();
}
public void Checking() // run this function every 20 seconds
{ // some code here
}
You can use the C# Timer class
public void Main()
{
var myTimer = new Timer(20000);
myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
myTimer.Enabled = true;
Console.ReadLine();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
Main()
{
Timer tm = new Timer();
tm.Interval = 20000;//Milliseconds
tm.Tick += new EventHandler(tm_Tick);
tm.Start();
}
void tm_Tick(object sender, EventArgs e)
{
Checking();
}
public void Checking()
{
// Your code
}
Ok so I am using System.Timers.Timer in .Net 4 with C#.
I have my timer object like so:
var timer = new Timer {Interval = 123};
I have my Timer Elapsed event handler pointed at a method like so:
timer.Elapsed += MyElapsedMethod;
And my method looks like this:
static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Foo Bar");
}
I want to pass a string into this method, how do I do this?
Thanks
The easiest way to do this is to change the event handler into an anonymous function. It allows you to pass the string at the point of declaration.
string theString = ...;
timer.Elapsed += (sender, e) => MyElapsedMethod(sender, e, theString);
static void MyElapsedMethod(object sender, ElapsedEventArgs e, string theString) {
...
}
If you want to be able to unregister your "Elapsed" event handler again, you shouldn't use a delegate without remembering it in a variable.
So another solution could be to create a custom class based on Timer. Just add whatever members you like and get your custom Timer object back from the "sender" argument of the "Elapsed" event handler:
class CustomTimer : System.Timers.Timer
{
public string Data;
}
private void StartTimer()
{
var timer = new CustomTimer
{
Interval = 3000,
Data = "Foo Bar"
};
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
string data = ((CustomTimer)sender).Data;
}
This strategy of course works for other events and classes too, as long as the base class is not sealed.
You can save string in some object and read it in event handler:
static string _value;
static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
Console.WriteLine(_value);
}
UPDATE: same code via different syntax:
timer.Elapsed += (s,e) => Console.WriteLine(_value);
UPDATE: Consider also using System.Threading.Timer instead
State state = new State();
Timer timer = new Timer(OnTimer, state, 0, 123);
state.Value = "FooBar"; // change state object
You can retrieve state in timer callback:
static void OnTimer(object obj)
{
State state = obj as State;
if (state == null)
return;
Console.WriteLine(state.Value);
}
Timer aTimer = new Timer(300);
aTimer.Elapsed += delegate { PublishGPSData(channel, locationViewModel); };
// Hook up the Elapsed event for the timer.
aTimer.AutoReset = true;
aTimer.Enabled = true;
private void PublishGPSData(IModel channel, LocationViewModel locationViewModel)
{
};
Use a field in the same class to hold whatever string you want and then retrieve it in you elapsed event handler. You'll have to be careful about cross-threading issues however.
I wrote this simple class to handle this:
using System;
using System.Timers;
namespace MyProject.Helpers
{
public class MyTimer
{
private volatile Timer _timer = new Timer();
private volatile bool _requestStop = false;
private MyElapsedEventHandler _eventHander;
private MyElapsedEventHandlerWithParam _eventHandlerWithParam;
private object _param;
public MyTimer(int interval, MyElapsedEventHandler elapsedEventHandler, bool autoReset = false)
{
_timer.Interval = interval;
_timer.Elapsed += ElapsedWrapper;
_timer.AutoReset = autoReset;
_eventHander = elapsedEventHandler;
Start();
}
public MyTimer(int interval, MyElapsedEventHandlerWithParam elapsedEventHandler, object param, bool autoReset = false)
{
_timer.Interval = interval;
_timer.Elapsed += ElapsedWrapperWithParam;
_timer.AutoReset = autoReset;
_eventHandlerWithParam = elapsedEventHandler;
_param = param;
Start();
}
private void ElapsedWrapper(object sender, ElapsedEventArgs e)
{
if (!_requestStop && _eventHander != null)
{
_eventHander();
}
}
private void ElapsedWrapperWithParam(object sender, ElapsedEventArgs e)
{
if (!_requestStop && _eventHandlerWithParam != null)
{
_eventHandlerWithParam(_param);
}
}
public void Stop()
{
_requestStop = true;
_timer.Stop();
}
public void Start()
{
_requestStop = false;
_timer.Start();
}
}
public delegate void MyElapsedEventHandlerWithParam(object param);
public delegate void MyElapsedEventHandler();
}
use it like this:
void Main(string[] args){
new MyTimer(durationInSeconds * 1000, EventHandler, "some string");
}
void EventHandler(object param){
doSomethingWithString((string)param);
}
you can also pass the event arguments or any kind of parameters if you edit the delegate (and the call of the event handler in MyTimer class).
Why not just use a Timer and an ElapsedEventHandler?
namespace TimerEventHandler
{
class Program
{
private static Timer myEventTimer;
static void Main(string[] args)
{
// 5 second timer multiply 1000 milliseconds by the time
//e.g. new Timer(60 * 1000 * 10) = 10 minutes
myEventTimer = new Timer(5 * 1000 * 1);
myEventTimer.Enabled = true;
myEventTimer.Elapsed += new ElapsedEventHandler(TimerSchedule_Elapsed);
Console.WriteLine("Timer started!");
// make a thread and wait forever just so console does not go away
Thread.Sleep(Timeout.Infinite);
}
private static void TimerSchedule_Elapsed(object sender, ElapsedEventArgs e)
{
// do something
Console.WriteLine("Timer elapsed!");
}
}
}
hey i am new to c# plz help.
i am writing a program that sorts data in a file and it is a time consuming process so i thought that i should run it in a separate thread and since it has alot of step so i made a new class for it. the problem is that i want to show the progress in the main GUI and i know for that i have to use Invoke function but the problem is that the form control variables are not accessible it this class. what should i do ??????
sample code:
public class Sorter
{
private string _path;
public Sorter(string path)
{
_path = path;
}
public void StartSort()
{
try
{
processFiles(_path, "h4x0r"); // Just kidding
}
catch (Exception e)
{
MessageBox.Show("Error: " + e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void processFiles(string Dir, string[] key)
{
/* sorting program */
}
and it is used as
public partial class Form1 : Form
{
Sorter sort;
public Form1()
{
InitializeComponent();
}
private void browseBtn_Click(object sender, EventArgs e)
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
textBox1.Text = folderBrowserDialog1.SelectedPath;
}
private void startBtn_Click(object sender, EventArgs e)
{
if (startBtn.Text == "Start Sorting")
{
Thread worker = new Thread(new ThreadStart(delegate() {
sort = new Sorter(textBox1.Text);
sort.StartSort(); }));
worker.start();
}
else
MessageBox.Show("Cancel");//TODO: add cancelling code here
}
}
plz help..
Add an Event to your class that is doing the multi-threaded work, that triggers when the progress changes. Have your form subscribe to this event and update the progress bar.
Note ProgressEventArgs is a little class that inherits EventArgs and has an Integer for the progress.
// delegate to update progress
public delegate void ProgressChangedEventHandler(Object sender, ProgressEventArgs e);
// Event added to your worker class.
public event ProgressChangedEventHandler ProgressUpdateEvent
// Method to raise the event
public void UpdateProgress(object sender, ProgressEventArgs e)
{
ProgressChangedEventHandler handler;
lock (progressUpdateEventLock)
{
handler = progressUpdateEvent;
}
if (handler != null)
handler(sender, e);
}
I would recommend you read up on the BackgroundWorker class. It is exactly for the problem you are trying to solve and makes things a lot easier than doing manual threading yourself.
Brief Example
public Form1()
{
InitializeComponent();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.WorkerSupportsCancellation = true;
backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
}
void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void btnStart_Click(object sender, EventArgs e)
{
if (!backgroundWorker.IsBusy)
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i < 101; ++i)
{
if (backgroundWorker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
//Sort Logic is in here.
Thread.Sleep(250);
backgroundWorker.ReportProgress(i);
}
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker.IsBusy && backgroundWorker.WorkerSupportsCancellation)
backgroundWorker.CancelAsync();
}
You could do something like this:
public delegate void StatusReporter(double progressPercentage);
public class MainClass
{
public void MainMethod()
{
Worker worker = new Worker(ReportProgress);
ThreadStart start = worker.DoWork;
Thread workThread = new Thread(start);
workThread.Start();
}
private void ReportProgress(double progressPercentage)
{
//Report here!!!
}
}
public class Worker
{
private readonly StatusReporter _reportProgress;
public Worker(StatusReporter reportProgress)
{
_reportProgress = reportProgress;
}
public void DoWork()
{
for (int i = 0; i < 100; i++ )
{
// WORK, WORK, WORK
_reportProgress(i);
}
}
}
There are a few option available to solve this sort of issue. In any case, you will have to fiddle with Invoke to get the UI to update.
You could...
...add an event that fires on your new class which your UI can listen to, and Invoke as applicable - you'd still need to pass the data to your worker class (by constructor, properties, method call, etc)
...keep the method as a method on your form, and pas that to start your new thread from (after all, a new thread doesn't have to be starting in a different class)
...change the access modifiers on your controls to be (say) internal such that any class within the same assembly can Invoke changes to the controls, or read from them.
...make your worker class a child of the form it needs to access - it can then see the privates of its parent, as long as it is passed a reference to the instance.