I make a call via client side to initiate the StopTickerTimer function which successfully calls the StopTickerTimer function but unfortunately doesn't actually stop the timer. The timer starts and works properly but I can't seem to understand why my timer isn't stopping. I've tried setting timer.Enabled = false. I've tried various solutions that I've found on here but nothing seems to work.
public Timer timer = new Timer();
private string jsonContents;
private string currentTickerPlaylist;
private int i = 0;
private List<string> playlistTickers;
public void StartTickerTimer(int seconds, string selectedPlaylist)
{
currentTickerPlaylist = selectedPlaylist;
InitPlaylistTickerTimer(seconds);
}
public void StopTickerTimer()
{
StopTimer();
}
private void InitPlaylistTickerTimer(int seconds)
{
timer.Elapsed += new ElapsedEventHandler(t_Tick);
timer.Interval = seconds * 1000;
timer.AutoReset = true;
timer.Start();
}
private void StopTimer()
{
timer.Stop();
}
private void t_Tick(object sender, EventArgs e)
{
SetPlaylistTickerSettings();
if (i >= playlistTickers.Count)
{
i = 0;
Payload ticker = new Payload
{
ticker = playlistTickers[i]
};
Payload ticker2 = new Payload
{
payload = ticker
};
var json = ServiceStack.Text.JsonSerializer.SerializeToString(ticker2);
PutToSingular("url", json);
i++;
}
else
{
Payload ticker = new Payload
{
ticker = playlistTickers[i]
};
Payload ticker2 = new Payload
{
payload = ticker
};
var json = ServiceStack.Text.JsonSerializer.SerializeToString(ticker2);
PutToSingular("url", json);
i++;
}
}
You started your timer, but you are not calling your "StopTimer" anywhere in the code...
Related
I would like to check updates from txt file on web server. and send a messagebox when there is version mismatch, I'm using this code and it works but I want it only to connect the server every 10 minutes and check the text file.
is there any option to do that?
maybe using another way to create this loop?
I also would like to send the messagebox only once
bool hasDisplayed = false;
private string UpdateCheckServer()
{
WebClient client = new WebClient();
Stream stream = client.OpenRead("http://localhost/update/update_version.txt");
StreamReader reader = new StreamReader(stream);
string serverversion = reader.ReadToEnd();
return serverversion;
}
private string UpdateCheckClient()
{
string ClientVersion = System.IO.File.ReadAllText("update_version.txt");
return ClientVersion;
}
private void UpdateCheckTimer()
{
while (!hasDisplayed)
{
if (starter.Enabled == true && UpdateCheckServer() == UpdateCheckClient())
{
//Nothing here
}
if (starter.Enabled == true && UpdateCheckServer() != UpdateCheckClient())
{
MessageBox.Show("not updated");
hasDisplayed = true;
}
}
An implementation based on timer can look like this:
private bool _equalVersion = true;
private System.Timers.Timer _timer = new System.Timers.Timer(1000 * 60 * 10); //millisecond * seconds * minutes
private void StartUpdateCheckTimer()
{
_timer.Elapsed += UpdateCheck;
_timer.Start();
}
private void UpdateCheck(object sender, ElapsedEventArgs e)
{
_timer.Stop();
_equalVersion = (UpdateCheckServer() == UpdateCheckClient());
if (!_equalVersion)
{
MessageBox.Show("not updated");
}
else
{
_timer.Start();
}
}
in this way you get a timer:
triggered each 10 minutes,
performing the check
notifying the version change (and stopping) or proceeding with the subsequent iterations
then you can add some more logic like for example reset of the check, more proper notification action (separating your check routine from the GUI part) and many more.
Another approach (as pointed out by #imsmn) can be to make your implementation System.Threading.Sleep based, but I'd suggest the first option based on timer.
After several tries and learning I managed to do that.
private string UpdateCheckServer()
{
WebClient client = new WebClient();
Stream stream = client.OpenRead("http://localhost/update/update_version.txt");
StreamReader reader = new StreamReader(stream);
string serverversion = reader.ReadToEnd();
return serverversion;
}
private string UpdateCheckClient()
{
string ClientVersion = System.IO.File.ReadAllText("update_version.txt");
return ClientVersion;
}
private void UpdateCheckTimer()
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 15000; // specify interval time as you want
t.Tick += new EventHandler(timer_Tick);
t.Start();
void timer_Tick(object sender, EventArgs e)
{
//Call method
if (starter.Enabled == true && UpdateCheckServer() != UpdateCheckClient())
{
t.Stop();
MessageBox.Show("not updated");
}
}
}
I am generating data every 1 second to write in a file but I want a new file every 5 minutes rather than every 1 second and want to writes all 5 minutes data into that file.
Below code generate a new file every 1 second and for that period data writes in the file. How I can generate a new file every 5 minutes?
static void Main(string[] args)
{
var incremental = 0;
while (true)
{
Go(incremental);
incremental++;
Thread.Sleep(1000);
}
}
private static void Go(int incremental)
{
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
using var rewrite = new StreamWriter(fileFullPath);
rewrite.WriteLine(incremental);
}
private static string GetDynamicFullPath(string basePath)
{
var dynamicFileName = $"file-{DateTime.Now:yyyyMMddHHmmssfff}.txt";
return basePath + dynamicFileName;
}
This is exactly the case where the .Net Reactive library (System.Reactive) shines.
Install it via NuGet package maneger, then the code will look like this:
1:declare buffer variable:
private readonly Subject<int> _myBuffer = new Subject<int>();
2:setup buffer subscription
_myBuffer.Buffer(TimeSpan.FromMinutes(5))
.Subscribe(bufferData => Go(bufferData.ToArray()));
3:your Do method is little changed to accept array of ints
private void Go(int[] bufferData)
{
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
using var rewrite = new StreamWriter(fileFullPath);
rewrite.WriteLine(bufferData);
}
4:finally, the infinite loop
var incremental = 0;
while (true)
{
_myBuffer.OnNext(incremental++);
Thread.Sleep(1000);
}
It can not be simpler!
The point is that Buffer method will automatically collect all received data for the specified period. You just need to subscribe to it (start listening to it) and then your `Do' method will be executed every 5 minutes with the buffered data.
I would suggest the simplest solution:
You can store a datetime when the last file was created.
You can also define a 5 mins threshold.
You should call the file create method when the current datetime is greater than the sum of the last created timestamp and the threshold.
Sample code:
private static readonly TimeSpan threshold = TimeSpan.FromMinutes(5);
private static DateTime lastCreated = DateTime.UtcNow;
public static void Main()
{
while(true)
{
if(DateTime.UtcNow >= lastCreated.Add(threshold))
{
//call the file create method
lastCreated = DateTime.UtcNow;
}
Thread.Sleep(1000);
}
}
I would advice you to use a Timer to flush and create the files all 5 Minutes. You then also should use a SemaphoreSlim to synchronize the access to the StreamWriter, because the callback for the timer may be executed on any Thread-Pool-Thread.
So I would do something like:
public static StreamWriter writer;
public static SemaphoreSlim mutex;
static void Main(string[] args)
{
mutex = new SemaphoreSlim(1,1);
var incremental = 0;
using var timer = new Timer(5 * 60 * 1000);
static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
CreateNewFile();
}
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
while (true)
{
WriteData(incremental);
Thread.Sleep(1000);
incremental++;
}
}
private static void WriteData(int data)
{
mutex.Wait();
try
{
// write you data ...
}
finally
{
mutex.Release();
}
}
private static void CreateNewFile()
{
mutex.Wait();
try
{
if (writer != null)
{
writer.Dispose();
writer = null;
}
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
writer = new StreamWriter(fileFullPath);
}
finally
{
mutex.Release();
}
}
private static string GetDynamicFullPath(string basePath)
{
var dynamicFileName = $"file-{DateTime.Now:yyyyMMddHHmmssfff}.txt";
return basePath + dynamicFileName;
}
In addition I would suggest to use the async versions of all these methodes. So WaitAsync(), WriteLineAsync, ...
public static StreamWriter writer;
public static SemaphoreSlim mutex;
static async Task Main(string[] args)
{
mutex = new SemaphoreSlim(1, 1);
var incremental = 0;
using var timer = new Timer(5 * 60 * 1000);
static async void Timer_ElapsedAsync(object sender, ElapsedEventArgs e)
{
await CreateNewFileAsync();
}
timer.Elapsed += Timer_ElapsedAsync;
timer.AutoReset = true;
timer.Start();
while (true)
{
await WriteDataAsync(incremental);
await Task.Delay(1000);
incremental++;
}
}
private static async Task WriteDataAsync(int data)
{
await mutex.WaitAsync();
try
{
// write you data ...
await writer.WriteLineAsync(data.ToString());
}
finally
{
mutex.Release();
}
}
private static async Task CreateNewFileAsync()
{
await mutex.WaitAsync();
try
{
if (writer != null)
{
await writer.DisposeAsync();
writer = null;
}
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
writer = new StreamWriter(fileFullPath);
}
finally
{
mutex.Release();
}
}
private static string GetDynamicFullPath(string basePath)
{
var dynamicFileName = $"file-{DateTime.Now:yyyyMMddHHmmssfff}.txt";
return basePath + dynamicFileName;
}
I'am trying to create watch folder aplicaction in C# that will do an action when new file will arrive. Since the watched folder is on GPFS share I'am unable to use FileSystemWatcher (which works fine for me in NTFS). So I've based the app on other collegue solution.
The app shows nicely "Timer starts" message but when it comes to
timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
it did not calls the DoStuff method - "Starting new files proc" message never show up. What I've done wrong? Here is complete code:
namespace MonitorFolderActivity
{
public partial class frmMain : Form
{
List<string> fileList = new List<string>();
System.Timers.Timer timer;
DateTime LastChecked;
public frmMain()
{
InitializeComponent();
}
private void abortAcitivityMonitoring()
{
btnStart_Stop.Text = "Start";
txtActivity.Focus();
}
private void startActivityMonitoring(string sPath)
{
if (sPath.Length < 3)
{
MessageBox.Show("You have to enter a folder to monitor.",
"Hey..!", MessageBoxButtons.OK, MessageBoxIcon.Stop);
abortAcitivityMonitoring();
}
else
{
TS_AddLogText(string.Format("Timer starts\r\n"));
timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
}
}
private void stopActivityMonitoring()
{
TS_AddLogText(string.Format("Timer stops\r\n"));
this.timer.Stop();
}
private void DoStuff(object sender, System.Timers.ElapsedEventArgs e)
{
TS_AddLogText(string.Format("Starting new files proc\r\n"));
LastChecked = DateTime.Now;
string[] files = System.IO.Directory.GetFiles("D:\\MEDIAIN\\", "*", System.IO.SearchOption.AllDirectories);
foreach (string file in files)
{
if (!fileList.Contains(file))
{
fileList.Add(file);
TS_AddLogText(string.Format(file));
}
}
TimeSpan ts = DateTime.Now.Subtract(LastChecked);
TimeSpan MaxWaitTime = TimeSpan.FromMinutes(1);
if (MaxWaitTime.Subtract(ts).CompareTo(TimeSpan.Zero) > -1)
timer.Interval = MaxWaitTime.Subtract(ts).TotalMilliseconds;
else
timer.Interval = 1;
timer.Start();
}
private delegate void AddLogText(string text);
private void TS_AddLogText(string text)
{
if (this.InvokeRequired)
{
AddLogText del = new AddLogText(TS_AddLogText);
Invoke(del, text);
}
else
{
txtActivity.Text += text;
}
}
private void btnStart_Stop_Click(object sender, EventArgs e)
{
if (btnStart_Stop.Text.Equals("Start"))
{
btnStart_Stop.Text = "Stop";
startActivityMonitoring(txtFolderPath.Text);
}
else
{
btnStart_Stop.Text = "Start";
stopActivityMonitoring();
}
}
private void lblActivity_Click(object sender, EventArgs e)
{
}
private void lblToMonitor_Click(object sender, EventArgs e)
{
}
}
}
There are few issues in your code.
First of all you are not setting the time at which timer should elapse, which means it will read the default value which is
100 ms
Secondly you are not starting your timer. You need to add this line to your code in this method startActivityMonitoring else statement.
timer.Interval = yourdesiredinterval;
timer.Start();
Thirdly, as you are doing stop and start (by looks of your code) you should not create a new timer on each call of your startActivityMonitoring method. Rather you should do this
If(timer == null)
{
timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Interval = yourinterval;
timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
}
timer.Start();
In your else clause, you never start the timer. Here's a fix:
else
{
TS_AddLogText(string.Format("Timer starts\r\n"));
timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
timer.Start();
}
I have this code:
autoResetEvent = new AutoResetEvent(false);
clien = new WebClient();
clien.Encoding = Encoding.UTF8;
clien.DownloadDataCompleted += new DownloadDataCompletedEventHandler(clien_DownloadDataCompleted);
clien.DownloadDataAsync(new Uri("http://www.classoneequipment.com/"));
autoResetEvent.WaitOne();
void clien_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
Encoding enc = Encoding.UTF8;
myString = enc.GetString(e.Result);
autoResetEvent.Set();
}
When I run this code in a button click event - It works fine. but when I run the code from big class it gets stucked and don't arrive to the func: clien_DownloadDataCompleted.
You approach it all wrong. If you want to download 3000 or more pages you got to be a bit more efficient and not wait on the event from each download.
Implementation (just a rough draft, you have to complete it)
public class Downloader
{
ConcurrentQueue<Uri> _queue = new ConcurrentQueue<Uri>();
int _maxWorkers = 10;
long _currentWorkers = 0;
ManualResetEvent _completed;
public void Enqueue(Uri uri)
{
_queue.Enqueue(uri);
if (Interlocked.Read(_currentWorkers) < _maxWorkers)
{
// not very thread safe, but we just want to limit the workers
// within a reasonable limit. 1 or 2 more doesn't really matter.
Interlocked.Increment(_currentWorkers);
// yes, i'm a bit old fashioned.
TriggerJob();
}
}
private void TriggerJob()
{
Uri uri;
if (!_queue.TryDequeue(out uri))
{
Interlocked.Decrement(_currentWorkers);
return;
}
var client = new WebClient();
client.Encoding = Encoding.UTF8;
client.DownloadDataCompleted += DownloadDataCompleted;
client.DownloadDataAsync(uri);
}
private void DownloadDataCallback(object sender, DownloadDataCompletedEventArgs e)
{
try
{
// If the request was not canceled and did not throw
// an exception, display the resource.
if (!e.Cancelled && e.Error == null)
{
var args = new DownloadedEventArgs { uri = e.Uri, data = (byte[])e.result};
DownloadCompleted(this, args)
}
else
{
var args = new DownloadFailedEventArgs { uri = e.Uri, error = e.Error };
DownloadFailed(this, args);
}
}
catch (Exception err)
{
var args = new DownloadFailedEventArgs { uri = e.Uri, error = err };
DownloadFailed(this, args);
}
TriggerJob();
}
public event EventHandler<DownloadedEventArgs> DownloadCompleted = delegate{};
public event EventHandler<DownloadFailedEventArgs> DownloadFailed = delegate{};
}
public class DownloadedEventArgs
{
public Uri uri;
public byte[] data;
}
public class DownloadFailedEventArgs
{
public Uri uri;
public Exception error;
}
Usage:
var downloader = new Downloader();
downloader.Completed += (o,e) { Console.WriteLine("Whoohoho, completed: " + e.Uri); };
for (x = 1; x < 100000; x++)
{
downloader.Enqueue(new Uri("http://somewhere.com));
}
I want my application will show on my form my class properties so I started my class with BackgroundWorker and create ProgressChanged.
my class:
public class DumpFile
{
PacketDevice _device;
public int _packetsCount;
public double _bitsPerSecond;
public double _packetsPerSecond;
public DateTime _lastTimestamp;
public delegate void dlgPackProgress(int progress);
public event dlgPackProgress evePacketProgress;
public DumpFile(PacketDevice device, string pcapPath)
{
_device = device;
_pcapPath = pcapPath;
_packetsCount = 1;
}
public void startCapturing()
{
OnPacketProgress(_packetsCount++);
using (PacketCommunicator communicator = _device.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000)) //open the device
{
ThreadStart starter = delegate { openAdapterForStatistics(_device); };
new Thread(starter).Start();
using (PacketDumpFile dumpFile = communicator.OpenDump(_pcapPath)) //open the dump file
{
communicator.ReceivePackets(0, dumpFile.Dump); //start the capture
}
}
}
private void OnPacketProgress(int packet)
{
var handler = evePacketProgress;
if (handler != null)
{
handler(packet);
}
}
public void openAdapterForStatistics(PacketDevice selectedOutputDevice)
{
using (PacketCommunicator statCommunicator = selectedOutputDevice.Open(100, PacketDeviceOpenAttributes.Promiscuous, 1000)) //open the output adapter
{
ThreadStart start = delegate { test(selectedOutputDevice); };
new Thread(start).Start();
statCommunicator.SetFilter("tcp"); //compile and set the filter
statCommunicator.Mode = PacketCommunicatorMode.Statistics; //put the interface in statstics mode
statCommunicator.ReceiveStatistics(0, StatisticsHandler);
}
}
public void test(PacketDevice selectedOutputDevice)
{
using (PacketCommunicator communicator = selectedOutputDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
communicator.ReceivePackets(0, PacketHandler);
}
}
private void PacketHandler(Packet packet)
{
string result = _packetsCount.ToString() + ". " + packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + packet.Length;
_packetsCount++;
}
private void StatisticsHandler(PacketSampleStatistics statistics)
{
DateTime currentTimestamp = statistics.Timestamp; //current sample time
DateTime previousTimestamp = _lastTimestamp; //previous sample time
_lastTimestamp = currentTimestamp; //set _lastTimestamp for the next iteration
if (previousTimestamp == DateTime.MinValue) //if there wasn't a previous sample than skip this iteration (it's the first iteration)
{
return;
}
double delayInSeconds = (currentTimestamp - previousTimestamp).TotalSeconds; //calculate the delay from the last sample
_bitsPerSecond = statistics.AcceptedBytes * 8 / delayInSeconds; //calculate bits per second
_packetsPerSecond = statistics.AcceptedPackets / delayInSeconds; //calculate packets per second
}
}
start button who start capturing:
private void btnStartCapture_Click(object sender, EventArgs e)
{
timerSniffer.Start();
btnStartTabSniffer.Enabled = false;
btnStopTabSniffer.Enabled = true;
groupBoxSelectTabSniffer.Enabled = false;
bgWorker = new BackgroundWorker();
bgWorker.WorkerReportsProgress = true;
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWSniffer_ProgressChanged);
bgWorker.DoWork += new DoWorkEventHandler(
(s3, e3) =>
{
DumpFile dumpFile = new DumpFile(deviceForCapturing, pcapFilePathSniffer);
tshark.evePacketProgress += new DumpFile.dlgPackProgress(
(packet) =>
{
bgWorker.ReportProgress(packet, dumpFile);
});
dumpFile.startCapturing();
});
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
(s3, e3) =>
{
groupBoxSelectTabSniffer.Enabled = true;
});
bgWorker.RunWorkerAsync();
}
ProgressChanged:
private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var dumpFile = (DumpFile)e.UserState;
lblNumberOfPacketsTabSniffer2.Text = dumpFile._packetsCount.ToString("#,##0");
lblTrafficRateTabSniffer2.Text = (dumpFile._bitsPerSecond * 0.000001).ToString("0.##") + " Mbit/sec" + " (" + dumpFile._bitsPerSecond.ToString("#,##0") + " Bits/sec" + ")";
lblPacketsRateTabSniffer2.Text = dumpFile._packetsPerSecond.ToString("#,##0") + " Packets/sec";
}
the problem is that my application "get into" ProgressChanged functions but only in one time.
I think I missed something in my class.
I can only find one call to OnPacketProgress(), and it's outside of any loop.
public void startCapturing()
{
OnPacketProgress(_packetsCount++);
....
}
So Yes, that will only be called once.
You need something inside ReceivePackets()