I get an error when network is disconnected - c#

I have a C# windows form that is running automatically (as I have a timer set at the beginning). It is going to read and insert some records into the table. This program giving me error when network is disconnected. I want it resume working after network back as it is running automatically.
this is the program:
private void UtilityForm_Load(object sender, EventArgs e)
{
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(tmrProcess_Tick);
timer.AutoReset = true;
timer.SynchronizingObject = this;
timer.Interval = 1000;
timer.Enabled = true;
}
private void tmrProcess_Tick(object sender, EventArgs e)
{
ProcessLeads();
}
private void ProcessLeads()
{
tmrProcess.Stop();
lblActive.BackColor = Color.Red;
Application.DoEvents();
//I m getting error here
TransmissionBuilder transmissionBuilder = new TransmissionBuilder();
TransmissionAgent transmissionAgent = new TransmissionAgent();
int leadCount = 0;
if (transmissionBuilder.Count > 0)
{
toolStripProgress.Maximum = transmissionBuilder.Count;
toolStripProgress.Minimum = 0;
toolStripProgress.Value = 0;
}
try
{
foreach (XDocument document in transmissionBuilder)
{
transmissionAgent.SendPingTransmission (transmissionBuilder.CurrentPingDocument);
if (transmissionAgent.PingWasAccepted)
{
transmissionAgent.SendLeadTransmission(
transmissionBuilder.CreateLeadDocument(
transmissionAgent.ReservationCode
)
);
}
TransmissionLog transmissionLog = new TransmissionLog();
transmissionLog.WriteLogEntry(
transmissionBuilder.CurrentApplicantId,
transmissionBuilder.CurrentPingDocument.ToString(),
transmissionAgent.PingResponse.ToString(),
transmissionBuilder.CurrentLeadDocument.ToString(),
transmissionAgent.LeadResponse.ToString(),
transmissionAgent.ReservationCode,
transmissionAgent.ConfirmationCode,
transmissionAgent.PingReason,
transmissionAgent.LeadReason,
transmissionAgent.PingWasAccepted,
transmissionAgent.LeadWasAccepted);
toolStripProgress.Value += 1;
lblMessage.Text = ++leadCount + " out of " + transmissionBuilder.Count.ToString() + " have been processed...";
Application.DoEvents();
if (!processIsRunning)
{
lblMessage.Text += " after " + leadCount.ToString() + " leads.";
toolStripProgress.Value = 0;
break;
}
}
transmissionBuilder.Dispose();
toolStripStart.Enabled = true;
toolStripProgress.Value = 0;
if (leadCount == 1)
lblMessage.Text = "1 lead was processed.";
else if (leadCount > 1)
lblMessage.Text = leadCount.ToString() + " leads were processed.";
else
lblMessage.Text = "Process is waiting for leads to send...";
}
catch (Exception e)
{
Utilities.LogError((long)transmissionBuilder.CurrentApplicantId, e.Message + e.StackTrace);
Utilities.WriteToFile(e.Message + "-----" + e.StackTrace);
lblMessage.Text = "Error while connecting with ACE Server. Retrying...";
}
finally
{
lblActive.BackColor = Color.Green;
tmrProcess.Start();
Application.DoEvents();
}
}
it gave me error at these lines:
TransmissionBuilder transmissionBuilder = new TransmissionBuilder();
TransmissionAgent transmissionAgent = new TransmissionAgent();
The error is:
A transport level error has been occured when receiving result from the server.(provider: TCP provider, error: 0 -The semaphore timeout period has expired)
I try to put try-catch but when network is disconnect I get error message as a loop like 1000 times till network connected and the program resume working after. How I can prevent it from giving me this error message?

Why not use a Flag before the loop and set to true when there is an error, like:
Boolean hasShownMessage = false;
foreach (XDocument document in transmissionBuilder)
{
// On catch change it
catch (Exception e)
{
if (!hasShownMessage)
{
Utilities.LogError((long)transmissionBuilder.CurrentApplicantId, e.Message + e.StackTrace);
Utilities.WriteToFile(e.Message + "-----" + e.StackTrace);
lblMessage.Text = "Error while connecting with ACE Server. Retrying...";
}
hasShownMessage = True; // Set the flag to True
}
}

Related

How to more efficiently set properties of multiple Form Controls

My problem is that I have multiple Forms Controls that I need to make visible/invisible/change text, based on the output of my code.
Obviously this is very easy to achieve but the code is ridiculously long due to how I've set it up.
I have 3 image boxes containing a red, green and orange 'light'.
When the ping action is started (button click or a timer) all the controls need to be set like so:
// ping 1
redLight1.Visible = true;
greenLight1.Visible = false;
orangeLight1.Visible = false;
status_Lbl1.Text = "Initiated...";
I need to do this 9 times, and the code looks a bit meh to me having this repeated this many times.
I have a ping object that sends a ping every second for x amount of time. If all of the pings are sent and received successfully then an imagebox containing a green circle becomes visible greenLight1.Visible = true, while all others are set redLight1.Visible = false, orangeLight1.Visible = false, etc.
I have 9 of these sets of 'traffic lights', with a different IP being pinged and a different outcome for each.
I feel there must be a way to iteratively change the values of each of these boxes using the fact they all follow the same naming convention with just a different number on the end corresponding to the ping object they represent.
Here's a more visual idea of what I want to achieve.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// int counter = 0
if (e.Cancelled == true)
{
status_Lbl1.Text = "Cancelled";
}
else if (e.Error != null)
{
status_Lbl1.Text = "Error: " + e.Error.Message;
}
else
{
foreach (Ping pingObj in pings)
{
if (pingObj.SuccessfulPings == 0)
{
Debug.WriteLine("Ping Object: " + pingObj.Fqdn + " failed to successfully ping");
// greenLight[i].Visible = false;
// orangeLight[i].Visible = false;
// redLight[i].Visible = true;
// counter++
}
else if (pingObj.FailedPings != 0)
{
Debug.WriteLine("Ping Object: " + pingObj.Fqdn + " failed to successfully ping: " + pingObj.FailedPings + " times.");
// greenLight[i].Visible = false;
// orangeLight[i].Visible = true;
// redLight[i].Visible = false;
// counter++
}
else
{
Debug.WriteLine("Ping Object: " + pingObj.Fqdn + " succesfully pinged: " + pingObj.SuccessfulPings + " times.");
// greenLight[i].Visible = false;
// orangeLight[i].Visible = false;
// redLight[i].Visible = false;
// counter++
}
}
}
}
Here's the method that creates/uses the ping objects just in case that is necessary
private async void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
// Create background worker
BackgroundWorker worker = (BackgroundWorker)sender;
// Write to log file
await file.WriteAsync("Starting job...\n");
await file.WriteAsync("Requested amount of pings: " + count + "\n");
// Create date object for logs
DateTime localDate = DateTime.Now;
for (int i = 0; i < count; i++)
{
// Create ping objects
System.Net.NetworkInformation.Ping pinger = new System.Net.NetworkInformation.Ping();
PingReply pingReply;
try
{
foreach (Ping pingObj in pings)
{
try
{
pingReply = pinger.Send(pingObj.IpAddress);
// Write log file
await file.WriteLineAsync(localDate.TimeOfDay + " | Friendly Name " + pingObj.FriendlyName + " | Ping: " + pingReply.Address + " | Status " + pingReply.Status + " | Time: " + pingReply.RoundtripTime);
if (pingReply.Status.ToString().Contains("Success"))
{
pingObj.SuccessfulPings += 1;
}
else // Unsuccessful ping has been sent
{
pingObj.FailedPings += 1;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
wait(1000);
}
catch (Exception b)
{
Debug.WriteLine(b.ToString());
}
}
}
catch (Exception a)
{
Debug.WriteLine(a.ToString());
}
}
You can use Controls.Find() and "search by name" with the recurse option:
Control ctl = this.Controls.Find("greenLight" + counter, true).FirstOrDefault() as Control;
if (ctl != null) {
ctl.Visible = false;
}

Multithread using backgroundworker and event handler

I'm developing a sample program to connect multiple device using backgroundworker. Each device connected will be add to the list as new object. After finished connecting all the devices, i wanted to add an event handler for each connected devices. The problem that i'm facing now is the event handler doesn't firing at all. Below are the sample codes.
The Connect click button event :
private void btnConnect_Click(object sender, EventArgs e)
{
using (BackgroundWorker m_oWorker = new BackgroundWorker())
{
m_oWorker.DoWork += delegate (object s, DoWorkEventArgs args)
{
int iIpStart = 0;
int iIpEnd = 0;
string strIp1 = string.Empty;
string strIp2 = string.Empty;
list.Clear();
string[] sIP1 = txtIpStart.Text.Trim().ToString().Split('.');
string[] sIP2 = txtIpEnd.Text.Trim().ToString().Split('.');
iIpStart = Convert.ToInt32(sIP1[3]);
iIpEnd = Convert.ToInt32(sIP2[3]);
strIp1 = sIP1[0] + "." + sIP1[1] + "." + sIP1[2] + ".";
strIp2 = sIP2[0] + "." + sIP2[1] + "." + sIP2[2] + ".";
Ping ping = new Ping();
PingReply reply = null;
int iIncre = 0;
int iVal = (100 / (iIpEnd - iIpStart));
for (int i = iIpStart; i <= iIpEnd; i++)
{
Thread.Sleep(100);
string strIpconnect = strIp1 + i.ToString();
Console.Write("ip address : " + strIpconnect + ", status: ");
reply = ping.Send(strIpconnect);
if (reply.Status.ToString() == "Success")
{
if (ConnectDevice(strIpconnect))
{
strLastDevice = strIpconnect + " Connected";
isconnected = true;
}
else
{
isconnected = false;
}
}
else
{
isconnected = false;
}
m_oWorker.ReportProgress(iIncre);
iIncre = iIncre + iVal;
}
m_oWorker.ReportProgress(100);
};
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
m_oWorker.RunWorkerAsync();
}
}
ConnectDevice function method. Connected device will be added to the list :
protected bool ConnectDevice(string sIP)
{
try
{
NewSDK sdk = new NewSDK();
if (sdk.Connect() == true)
{
list.Add(new objSDK { sdk = sdk, ipaddress = sIP });
return true;
}
else
{
}
}
catch() {}
return false;
}
the Backgroundworker :
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
btnListen.Enabled = true;
}
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
if (isconnected)
{
listBox2.Items.Add(strLastDevice);
string[] ssplit = sDeviceInfo.Split(';');
foreach (string sword in ssplit)
{
listBox1.Items.Add(sword);
}
}
}
The function to attached event :
private void RegisterEvent()
{
foreach (objSDK obj in list)
{
obj.sdk.OnTransaction += () =>
{
listBox1.Items.Add("ip : " + obj.IP + " transaction");
};
}
}
You have declared m_oWorker as a local variable. I'm guessing this was a mistake ( the m_ prefix should only be used for class member variables)?
Also, you declared it within a using statement, meaning that it that the framework will call Dispose() on it at the end of the using block. Even if you held on to a reference to it (and I don't think you do) it still means its resources will be deallocated, which is probably why it isn't handling any events.
I try another workaround by using thread and task and work perfectly. Thanks for all response

Skydrive wp7 App: GetAsync method stopped working

On my windows phone 7 Mango app I use the Microsoft.Live and Microsoft.Live.Controls references to download and upload on Skydrive. Logging in and uploading files works fine but whenever I call the "client.GetAsync("/me/skydrive/files");" on the LiveConnectClient the Callback result is empty just containing the error: "An error occurred while retrieving the resource. Try again later."
I try to retrieve the list of files with this method.
This error suddenly occured without any change on the source code of the app (I think..) which worked perfectly fine for quite a while until recently. At least I didn't change the code section for up- or downloading.
I tried out the "two-step verification" of Skydrive, still the same: can log in but not download.
Also updating the Live refercences to 5.5 didn't change anything.
Here is the code I use. The error occurs in the "getDir_Callback" in the "e" variable.
Scopes (wl.skydrive wl.skydrive_update) and clientId are specified in the SignInButton which triggers "btnSignin_SessionChanged".
private void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
connected = true;
processing = true;
client = new LiveConnectClient(e.Session);
client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);
client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(UploadCompleted);
client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(OnDownloadCompleted);
client.DownloadProgressChanged += new EventHandler<LiveDownloadProgressChangedEventArgs>(client_DownloadProgressChanged);
infoTextBlock.Text = "Signed in. Retrieving file IDs...";
client.GetAsync("me");
}
else
{
connected = false;
infoTextBlock.Text = "Not signed into Skydrive.";
client = null;
}
}
private void OnGetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
if (e.Error == null)
{
client.GetCompleted -= new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);
client.GetCompleted += getDir_Callback;
client.GetAsync("/me/skydrive/files");
client_id = (string)e.Result["id"];
if (e.Result.ContainsKey("first_name") && e.Result.ContainsKey("last_name"))
{
if (e.Result["first_name"] != null && e.Result["last_name"] != null)
{
infoTextBlock.Text = "Hello, " +
e.Result["first_name"].ToString() + " " +
e.Result["last_name"].ToString() + "!";
}
}
else
{
infoTextBlock.Text = "Hello, signed-in user!";
}
}
else
{
infoTextBlock.Text = "Error calling API: " +
e.Error.ToString();
}
processing = false;
}
public void getDir_Callback(object s, LiveOperationCompletedEventArgs e)
{
client.GetCompleted -= getDir_Callback;
//filling Dictionary with IDs of every file on SkyDrive
if (e.Result != null)
ParseDir(e);
if (!String.IsNullOrEmpty(e.Error.Message))
infoTextBlock.Text = e.Error.Message;
else
infoTextBlock.Text = "File-IDs loaded";
}
Yo shall use client.GetAsync("me/SkyDrive/files", null) in place of client.GetAsync("me");
This is my code and it works fine.
private void btnSignIn_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
try
{
if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(e.Session);
client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_GetCompleted);
client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_UploadCompleted);
client.GetAsync("me/SkyDrive/files", null);
client.DownloadAsync("me/SkyDrive", null);
canUpload = true;
ls = e.Session;
}
else
{
if (client != null)
{
MessageBox.Show("Signed out successfully!");
client.GetCompleted -= client_GetCompleted;
client.UploadCompleted -= client_UploadCompleted;
canUpload = false;
}
else
{
canUpload = false;
}
client = null;
canUpload = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void client_GetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
try
{
List<System.Object> listItems = new List<object>();
if (e.Result != null)
{
listItems = e.Result["data"] as List<object>;
for (int x = 0; x < listItems.Count(); x++)
{
Dictionary<string, object> file1 = listItems[x] as Dictionary<string, object>;
string fileName = file1["name"].ToString();
if (fileName == lstmeasu[0].Title)
{
folderID = file1["id"].ToString();
folderAlredyPresent = true;
}
}
}
}
catch (Exception)
{
MessageBox.Show("An error occured in getting skydrive folders, please try again later.");
}
}
It miraculously works again without me changing any code. It seems to be resolved on the other end. I have no clue what was wrong.

Why doesn't my disconnect button work?

I am working on this GUI for serial port application. I recently added stop and wait protocols to the application. Surprisingly my disconnect button stopped working. I have thought through the logic and I have not been able to find the problem.
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public bool packetreceived = false;
private SerialPort sp = null; //<---- serial port at form level
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
//delegate variable to disconnect
public AddDataDelegate disconnectDelegate = null;
public void AddDataMethod(String myString)
{
richTextBox1.AppendText(myString);
}
/**
* Takes byte array and returns a string representation
*
*/
public String parseUARTData(byte[] data)
{
if (data.Length == 11)
{
String rv = "";
DataFields d = new DataFields();
if (!packetreceived)
{
d = mainLogic.parseData(data);
packetreceived = true;
}
//TODO
System.Threading.Thread.Sleep(5000);
if (d.sequence == 0)
{
sp.Write("1\r\n");
}
else
{
sp.Write("0\r\n");
}
packetreceived = false;
//now display it as a string
rv += STR_OPCODE + " = " + d.opcode + "\n";
rv += STR_CRC + " = " + d.crc + "\n";
rv += STR_SEQ + " = " + d.sequence + "\n";
rv += STR_FLAGS + " = " + d.flags + "\n";
rv += STR_TEMP + " = " + d.temperature + "\n";
rv += STR_HUMID + " = " + d.humidity + "\n";
rv += STR_PH + " = " + d.ph + "\n";
return rv + "\n\n";
}
else
{
return Encoding.ASCII.GetString(data);
}
}
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string s = sp.ReadExisting();
if (disconnectDelegate != null)
{
disconnectDelegate.Invoke(s);
}
richTextBox1.Invoke(this.myDelegate, new Object[] { parseUARTData(Encoding.ASCII.GetBytes(s)) });
}
private void button1_Click(object sender, EventArgs e)
{
connect.Enabled = false;
try
{
// open port if not already open
// Note: exception occurs if Open when already open.
if (!sp.IsOpen)
{
//sp.PortName = this.comboBox1.SelectedItem.ToString();
sp.Open();
}
// send data to port
sp.Write("####,###########\r\n");
disconnect.Enabled = true;
}
catch (Exception)
{
// report exception to user
Console.WriteLine(e.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
connect.Enabled = true;
try
{
// open port if not already open
// Note: exception occurs if Open when already open.
if (sp.IsOpen)
{
// send data to port
sp.Write("+++\r\n");
//add the delegate
disconnectDelegate = new AddDataDelegate(onDisconnect);
//sp.WriteTimeout = 500;
// sp.Write("####,0\r\n");
}
}
catch (Exception)
{
Console.WriteLine(e.ToString());
}
finally
{
disconnect.Enabled = false;
}
}
public void OnApplicationExit(object sender, EventArgs e)
{
sp.Close();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//foreach (string port in ports)
//{
// comboBoxSerialPorts.Items.Add(port);
//}
}
private void onDisconnect(string msg)
{
string trimmedMsg = msg.Trim();
if (trimmedMsg.Equals("OK"))
{
//send the second time
sp.Write("##,0\r\n");
//null the object
disconnectDelegate = null;
}
}
private void comPort_Click(object sender, EventArgs e)
{
try
{
if (sp.IsOpen)
{
//send data to port
sp.Write("1\r\n");
MessageBox.Show("bluetooth is transmitting data...");
//message box telling user that you are asking for data.
}
}
catch (Exception)
{
// report exception to user
Console.WriteLine(e.ToString());
}
}

FileSystemWatcher stops catching events

I am writing a c# program to let me know when a file has been added or deleted. I run it on my Windows 7 machine and watch an FTP server on our network.
It works fine but will suddenly stop catching any events. I'm guessing that it might be losing connection to the server or there is a glitch in the network.
How can I handle this situation in the code. Is there some exception I can watch for and try to restart the FileSystemWatcher object.
Any suggestions and code samples would be appreciated.
I needed to add an error handler for the FileSystemWatcher
fileSystemWatcher.Error += new ErrorEventHandler(OnError);
And then add this code:
private void OnError(object source, ErrorEventArgs e)
{
if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
{
txtResults.Text += "Error: File System Watcher internal buffer overflow at " + DateTime.Now + "\r\n";
}
else
{
txtResults.Text += "Error: Watched directory not accessible at " + DateTime.Now + "\r\n";
}
NotAccessibleError(fileSystemWatcher ,e);
}
Here is how I reset the SystemFileWatcher object:
static void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e)
{
source.EnableRaisingEvents = false;
int iMaxAttempts = 120;
int iTimeOut = 30000;
int i = 0;
while (source.EnableRaisingEvents == false && i < iMaxAttempts)
{
i += 1;
try
{
source.EnableRaisingEvents = true;
}
catch
{
source.EnableRaisingEvents = false;
System.Threading.Thread.Sleep(iTimeOut);
}
}
}
I think this code should do what I want it to do.
The previous answer does not fix it completely, I had to reset the watcher not just turn it on and off.
I use filesystemwatcher on a window service
void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e)
{
int iMaxAttempts = 120;
int iTimeOut = 30000;
int i = 0;
while ((!Directory.Exists(source.Path) || source.EnableRaisingEvents == false) && i < iMaxAttempts)
{
i += 1;
try
{
source.EnableRaisingEvents = false;
if (!Directory.Exists(source.Path))
{
MyEventLog.WriteEntry("Directory Inaccessible " + source.Path + " at " + DateTime.Now.ToString("HH:mm:ss"));
System.Threading.Thread.Sleep(iTimeOut);
}
else
{
// ReInitialize the Component
source.Dispose();
source = null;
source = new System.IO.FileSystemWatcher();
((System.ComponentModel.ISupportInitialize)(source)).BeginInit();
source.EnableRaisingEvents = true;
source.Filter = "*.tif";
source.Path = #"\\server\dir";
source.NotifyFilter = System.IO.NotifyFilters.FileName;
source.Created += new System.IO.FileSystemEventHandler(fswCatchImages_Changed);
source.Renamed += new System.IO.RenamedEventHandler(fswCatchImages_Renamed);
source.Error += new ErrorEventHandler(OnError);
((System.ComponentModel.ISupportInitialize)(source)).EndInit();
MyEventLog.WriteEntry("Try to Restart RaisingEvents Watcher at " + DateTime.Now.ToString("HH:mm:ss"));
}
}
catch (Exception error)
{
MyEventLog.WriteEntry("Error trying Restart Service " + error.StackTrace + " at " + DateTime.Now.ToString("HH:mm:ss"));
source.EnableRaisingEvents = false;
System.Threading.Thread.Sleep(iTimeOut);
}
}
}
You can create a method that initiates the FileSystemWatcher, and in case of an error, just restart it.
private void WatchFile()
{
try
{
fsw = new FileSystemWatcher(path, filter)
{
EnableRaisingEvents = true
};
fsw.Changed += Fsw_Changed;
fsw.Error += Fsw_Error;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
private void Fsw_Error(object sender, ErrorEventArgs e)
{
Thread.Sleep(1000);
fsw.Changed -= Fsw_Changed;
fsw.Error -= Fsw_Error;
WatchFile();
}

Categories

Resources