I created a method that append data to file .txt and it executes on Button_Click method. But I want to save the data to file not when I click the button but after time automatically (ex. after couple minutes starting from Application_Start). How can I solve my problem?
static public bool appendToFileTxt(string input)
{
try
{
if (File.Exists(nameOfFile))
File.Copy(nameOfFile, nameOfFile + ".bak", true);
using (StreamWriter sw = new StreamWriter(nameOfFile, true)){
sw.WriteLine(input.Replace("\r", ""));
}
return true;
}
catch{
return false;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
appendToFileTxt(newInput);
}
You can use the Timer class for this usage.
// Simulate Application_Start
public static void Main()
{
var appendToFileTimer = new Timer(AppendToFile, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
}
public static void AppendToFile(Object state)
{
Console.WriteLine("Append to file");
}
Related
I have problem with downloading files through C#.
I have a class which handles downloading like this:
namespace Ultra_Script
{
class FileDownloader
{
private readonly string _url;
private readonly string _fullPathWheretoSave;
private bool _result = false;
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0);
public FileDownloader(string url, string fullPathWheretoSave)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentNullException("url");
if (string.IsNullOrEmpty(fullPathWheretoSave)) throw new ArgumentNullException("fullPathWhereToSave");
this._url = url;
this._fullPathWheretoSave = fullPathWheretoSave;
}
public bool StartDownload(int timeout)
{
try
{
System.IO.Directory.CreateDirectory(Path.GetDirectoryName(_fullPathWheretoSave));
if (File.Exists(_fullPathWheretoSave))
{
File.Delete(_fullPathWheretoSave);
}
using (WebClient client = new WebClient())
{
var ur = new Uri(_url);
//client.Credentials = new NetworkCredential("username", "password");
client.DownloadProgressChanged += WebClientDownloadProgressChanged;
client.DownloadFileCompleted += WebClientDownloadCompleted;
Console.WriteLine(#"Downloading File:");
client.DownloadFileAsync(ur, _fullPathWheretoSave);
_semaphore.Wait(timeout);
return _result && File.Exists(_fullPathWheretoSave);
}
}
catch (Exception e)
{
Console.WriteLine("Cant download file");
Console.Write(e);
return false;
}
finally
{
this._semaphore.Dispose();
}
}
private void WebClientDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
Console.Write("/r --> {0}%", e.ProgressPercentage);
}
private void WebClientDownloadCompleted(object sender, AsyncCompletedEventArgs args)
{
_result = !args.Cancelled;
if (!_result)
{
Console.Write(args.Error.ToString());
}
Console.WriteLine(Environment.NewLine + "Download Finished!");
_semaphore.Release();
}
public static bool DownloadFile(string url, string fullPathWhereToSave, int timeoutInMilliSec)
{
return new FileDownloader(url, fullPathWhereToSave).StartDownload(timeoutInMilliSec);
}
}
}
And i called it like this:
public static void InstallBasicSW()
{
var succes = FileDownloader.DownloadFile("https://github.com/Corbieman/Basic_SW/raw/master/JaVa.exe", "C:\\Windows", 99999999);
Console.WriteLine("Done - Succes: " + succes);
Console.ReadLine();
}
But only what im getting in Console is:
Download Finished!
Done - Succes: False;
I don't get any error message or progress bar. This message just pops up instantly. And file doesn't download into that path. Anybody know or have idea where can be the problem?
The parameter of method DownloadFile need the full file's path.
Try this :
public static void InstallBasicSW()
{
var succes = FileDownloader.DownloadFile("https://github.com/Corbieman/Basic_SW/raw/master/JaVa.exe", #"C:\Temps\JaVa.exe", 99999999);
Console.WriteLine("Done - Succes: " + succes);
Console.ReadLine();
}
Why have you this result?
I think it's because you pass a directory path instead of a file path.
The download cancel and finish immediately.
A explicit exception will be more helpful...
So problem was i had to run it as admin and correct the path like you said guys. Its working now, Thanks.
I am implementing a winform application that is supposed to do the following:
OnLoad, open an XML file reading required information while watching for any new changes to the file (incoming new information)
A timer performing certain actions based on the nature of the provided information from the XML file. Please note that the nature of the action depends on the content of the XML file
What is the best way to achieve this? Two threads? Async? Some starting point would be much appreciated.
I think you need like this structure. Firstly you read XML file and configure your custom MyConfigurationClass object. After this point you can configure FileSystemWatcher object. And finally, you can configure your task schedular object with your desired time interval.
public partial class MainWindow : Window
{
MyConfigurationClass configuration;
string filePath = #"./some.xml";
FileSystemWatcher fileWatcher = new FileSystemWatcher();
System.Timers.Timer timer = new System.Timers.Timer();
public MainWindow()
{
// First read action action for
var task = Task.Run(() => ReadXML());
InitializeComponent();
FileWatherConfigure();
TimerConfigure(task.Result);
}
private void FileWatherConfigure()
{
fileWatcher.Path = System.IO.Path.GetDirectoryName(filePath);
fileWatcher.Filter = System.IO.Path.GetFileName(filePath);
fileWatcher.Changed += FileWatcher_Changed;
fileWatcher.EnableRaisingEvents = true;
}
private void TimerConfigure(SomeClass someClass)
{
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = configuration.TimeInterval.TotalMilliseconds;
timer.Enabled = true;
}
private void FileWatcher_Changed(object sender, FileSystemEventArgs e)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
SomeClass someClass = ReadXML();
// Do whatever you want file change
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
timer.Stop();
try
{
// Schedule Operation
}
catch (Exception ex)
{
}
timer.Start();
}
private SomeClass ReadXML()
{
// Read file and do what ever you want
}
}
public class SomeClass
{
// Data from XML
}
public class MyConfigurationClass
{
public TimeSpan TimeInterval { get; set; }
}
In the overrided void onIncomingCall I open a new Background thread which shows a new (Popup) Form.
I try to pickup or decline the Call in this Form but then I get an System.AccessViolationException.
it seems that the current call object is locked and cannot be accessed from another Form.
If I use the currentcall.answer(prm) in the onIncomingCall void then the call is established successfully (without another Form and thread).
public class myaccount : Account
{
public override void onIncomingCall(OnIncomingCallParam prm)
{
Call call = new Call(this, prm.callId);
CallOpParam param = new CallOpParam();
param.statusCode = pjsip_status_code.PJSIP_SC_RINGING;
param.statusCode = pjsip_status_code.PJSIP_SC_OK;
pjsipfunctions.currentparam = param;
pjsipfunctions.currentcall = call;
var thread = new Thread(() =>
{
ShowPopup(call,prm.callId.ToString());
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
// Thread myCallingThread = new Thread(new ThreadStart(ShowPopup));
//myCallingThread.SetApartmentState(ApartmentState.STA);
//myCallingThread.IsBackground = true;
//myCallingThread.Start();
}
public void ShowPopup(Call myCall,string call_id)
{
IncommingCallPopup win = new IncommingCallPopup(ref myCall, call_id );
win.Show();
System.Windows.Threading.Dispatcher.Run();
}
}
#####################################
public IncommingCallPopup(ref Call info, string callid)
{
currentCall = info;
Callid = callid;
CurrentCall = currentCall;
Prm.statusCode = pjsip_status_code.PJSIP_SC_RINGING;
InitializeComponent();
labelCallId.Content = callid;
}
private void rejectcall(object sender, RoutedEventArgs e)
{
Prm.statusCode = pjsip_status_code.PJSIP_SC_DECLINE;
CurrentCall.hangup(Prm);
}
private void transfercall(object sender, RoutedEventArgs e)
{
}
private void takecall(object sender, RoutedEventArgs e)
{
Prm.statusCode = pjsip_status_code.PJSIP_SC_OK;
try
{
CurrentCall.answer(Prm);
}
catch(Exception ex)
{
}
}
After crazy searching and trying some things i've figured it out.
Every Thread must registered in the Endpoint that you can hangup, pickup or transfer your call in another Class(Window).
All you need is to write this Method in a Public class and call this void everytime you call your void from another window ->
public void callpopup(String number) {
checkThread();
//answer, decline or something else
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static void checkThread()
{
try
{
if (ep != null && !ep.libIsThreadRegistered())
ep.libRegisterThread(Thread.CurrentThread.Name);
}
catch (Exception e)
{
}
}
I have a timer as
public static System.Timers.Timer timer_get = new System.Timers.Timer();
timer_get.Elapsed += new ElapsedEventHandler(Get_OnTimedEvent);
timer_get.Interval = 1000;
timer_get.Enabled = true;
It is hitting this method.
public static void GetListFromDb()
{
try
{
DataTable dt = new DataTable();
//..here is i am filling datatable
Parallel.ForEach(dt.AsEnumerable(), row => {
GetDataFromApi(row);
});
}
catch (Exception e)
{
//..
}
}
Each row has irrelevant webrequest elements(url,type,etc). I am sending the webrequest method at the same time.
The problem is that that the webrequest takes more time than the timer clock with 1000ms resolution above. Running requests are frequently hitting this problem and I don't know how to solve it. Is there any way to detect if a method is already running with a specific parameter?
If you can identify each request by some key, you can manage a dictionary for "running" requests
public static System.Timers.Timer timer_get = new System.Timers.Timer();
private static ConcurrentDictionary<string, bool> _runningRequests = new ConcurrentDictionary<string, bool>();
And then
static void GetDataFromApi(DataRow row)
{
var requestKey = (string)row["Url"];
if (_runningRequests.TryAdd(requestKey, true))
{
try
{
//send web request
}
finally
{
bool alreadyRunning;
_runningRequests.TryRemove(requestKey, out alreadyRunning);
}
}
}
One way to do this is by setting the Timer's AutoReset property to false. This will make sure that your callback will not be re-entered until you manually tell the timer to fire again. This method would work well because Parallel.ForEach will not return until the loop has completed. Here's an example using your code:
namespace Test
{
class Program
{
public static System.Timers.Timer timer_get = new System.Timers.Timer();
public static void Main()
{
timer_get.Elapsed += new ElapsedEventHandler(Get_OnTimedEvent);
timer_get.Interval = 1000;
timer_get.AutoReset = false;
timer_get.Enabled = true;
Console.WriteLine("Any Key to Exit");
Console.ReadLine();
}
private static void Get_OnTimedEvent(object sender, ElapsedEventArgs e)
{
try
{
GetListFromDb();
}
finally
{
timer_get.Start();
}
}
public static void GetListFromDb()
{
try
{
Thread.Sleep(5000);
//..
//..
//..
}
catch (Exception e)
{
//..
}
}
}
}
I have the following code:
namespace SSS.RemoteTruckService
{
public partial class Startup : Form
{
private Timer _gpsTimer;
private Timer _ppsTimer;
private Timer _creditCardTimer;
private Timer _iniTimer;
public string Message
{
get { return richTextBox_Message.Text; }
set
{
richTextBox_Message.Invoke((MethodInvoker)(()
=> richTextBox_Message.Text = DateTime.Now + " " +
value + Environment.NewLine + richTextBox_Message.Text));
}
}
public Startup()
{
InitializeComponent();
}
private void ButtonStartClick(object sender, EventArgs e)
{
StartRemoteTruck();
}
private void ButtonPauseClick(object sender, EventArgs e)
{
if (_gpsTimer.Enabled) _gpsTimer.Enabled = false;
if (_ppsTimer.Enabled) _ppsTimer.Enabled = false;
if (_creditCardTimer.Enabled) _creditCardTimer.Enabled = false;
if (_iniTimer.Enabled) _iniTimer.Enabled = false;
ProcessIniFile.StopProcess();
}
public void StartRemoteTruck()
{
Message = "RemoteTruck started.";
if (Settings.GlobalSettings == null)
{
Message = "GlobalSettings was null or not loaded. Cannot continue.";
Logging.Log("GlobalSettings was null or not loaded. Cannot continue.", "RemoteTruck", Apps.RemoteTruckService);
Environment.Exit(0);
}
if (Settings.GlobalSettings.IniFileWatcherEnabled)
{
ProcessIniFile.StartProcess();
}
CreateTimers();
}
And in the ProcessIniFile.StartProcess() I have the code:
namespace SSS.RemoteTruckService.inifile
{
public static class ProcessIniFile
{
private static DateTime _iniLastWriteTime;
private static readonly string Inifile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "sss.ini");
private static FileSystemWatcher _watcher;
public static void StartProcess()
{
ReadIniFile();
SaveCurrentIniReadings();
CreateIniFileWatcher();
}
public static void StopProcess()
{
if (_watcher != null)
{
_watcher.EnableRaisingEvents = false;
_watcher = null;
}
}
private static void CreateIniFileWatcher()
{
_watcher = new FileSystemWatcher
{
Path = Environment.GetFolderPath(Environment.SpecialFolder.Windows),
NotifyFilter = NotifyFilters.LastWrite,
Filter = "sss.ini"
};
_watcher.Changed += SssIniWatcherChanged;
_watcher.EnableRaisingEvents = true;
}
I'd like to pass back the the calling form the status of the reads of the file watcher.
Maybe I'm overthinking this, but if I want to add to the Message on the main form, how do I get to it?
You can use Events for that. Your process can send events and your form can handle them.
More info: http://msdn.microsoft.com/en-us/library/awbftdfh.aspx
The simple but not pretty way I like to use is to make that part of the form static as well. For example, creating a static variable WriteMessage, and in your Form Load or Startup(), you can set it:
WriteMessage = (s) => Message = s;
Sure this has some issues, but it's a quick way to get it done. One of those issues is that, you may need to use Dispatcher.invoke if you're not on the UI thread.