I was trying to ping a server using the Ping class, but after like 10 times that the method returns true, I keep getting false(which means the server is down[?] and it isn't) Here's the method:
public bool IsConnectedToInternet()
{
Ping p = new Ping();
try
{
PingReply reply = p.Send("www.uic.co.il", 1000);
if (reply.Status == IPStatus.Success)
return true;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
return false;
}
private void start_Click(object sender, EventArgs e)
{
for (; ; )
{
Console.WriteLine(IsConnectedToInternet);
}
}
Why am I keep getting false after a while?
Thank you.
You're flooding the server with requests:
for (; ; )
{
Console.WriteLine(IsConnectedToInternet);
}
will loop as fast as possible sending request after request.
If you are just coding a keep alive service or service status control then using a timer that pings every minute or even every 10 minutes should be good enough.
Additionally, as others have pointed out in their comments, you are abusing properties by doing the ping in the getter as the call can potentially take some time and property getters should really return, if not instantly then very quickly. A CheckConnection() method would have clearer intent.
I rewrote your code.
It will trigger an event called ConnectionLost if connection is lost and an event called Connected when it gets connected again.
public class NetworkStateMonitor
{
private System.Threading.Timer _timer;
bool _wasConnected = false;
public NetworkStateMonitor()
{
_timer = new System.Threading.Timer(OnPing, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
}
public bool CheckInternetConnection()
{
bool result = false;
Ping p = new Ping();
try
{
PingReply reply = p.Send("www.uic.co.il", 1000);
if (reply.Status == IPStatus.Success)
return true;
catch (PingException)
{
return false;
}
}
private void OnPing(object state)
{
var newState = CheckInternetConnection();
if (!newState && _wasConnected)
ConnectionLost(this, EventArgs.Empty);
else if (newState && !_wasConnected)
Connected(this, EventArgs.Empty);
_wasConnected = newState;
}
public event EventHandler ConnectionLost = delegate{};
public event EventHandler Connected = delegate{};
}
For other stumbling across this page, this function would be better if it were rewritten to:
public bool CheckInternetConnection(string HostName)
{
bool result = false; // assume error
try {
Ping oPing = new Ping();
PingReply reply = oPing.Send(HostName, 3000);
if (reply.Status == IPStatus.Success){
result = true;
}
} catch (Exception E) {
// Uncomment next line to see errors
// MessageBox.Show(E.ToString());
}
return result;
}
Now call using:
bool IsSuccessful = CheckInternetConnection("www.uic.co.il");
Related
Hi All: I want to run a function to check internet connection and update the UI content, so i'm using a Dispatchtimer in the WPF loaded, during the intenet check if the ping is blocked by the local server or for some x reasons the UI is blocking.
How can i call the function continuosly without blocking the UI & update the User interface? thanks.
private DispatcherTimer BackgroundAsyncTasksTimer;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
BackgroundAsyncTasksTimer = new DispatcherTimer();
BackgroundAsyncTasksTimer.Interval = TimeSpan.FromMilliseconds(2000);
BackgroundAsyncTasksTimer.Tick += BackgroundAsyncTasksTimer_Tick;
BackgroundAsyncTasksTimer.Start();
}
private async void BackgroundAsyncTasksTimer_Tick(object sender, object e)
{
if(CanConnectToTheInternet())
{
Dispatcher.Invoke((Action)delegate () {
einternetcoxn.Fill = (SolidColorBrush)new BrushConverter().ConvertFromString("#00ff00"); //Eclipse
checkNewversion();
bUpdatesoftware.IsEnabled = true;//button
});
}
else
{
Dispatcher.Invoke((Action)delegate () {
einternetcoxn.Fill = (SolidColorBrush)new BrushConverter().ConvertFromString("#841c34");
clearfields();
});
}
}
private static bool CanConnectToTheInternet()
{
try
{
string[] strArray = new string[5]
{
"8.8.8.8",
"https://www.google.com",
"https://www.microsoft.com",
"https://www.facebook.com",
};
if (((IEnumerable<string>)strArray).AsParallel<string>().Any<string>((Func<string, bool>)(url =>
{
try
{
Ping ping = new Ping();
byte[] buffer = new byte[32];
PingOptions options = new PingOptions();
if (ping.Send(url, 500, buffer, options).Status == IPStatus.Success)
return true;
}
catch
{
}
return false;
})))
return true;
if (((IEnumerable<string>)strArray).AsParallel<string>().Any<string>((Func<string, bool>)(url =>
{
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.KeepAlive = false;
httpWebRequest.Timeout = 5000;
using ((HttpWebResponse)httpWebRequest.GetResponse())
return true;
}
catch
{
}
return false;
})))
return true;
}
catch
{
return false;
}
return false;
}
A DispatcherTimeris not running the tick event on a background thread, at least not by default in a UI application.
But this should be fine if you change your CanConnectToTheInternetmethod to use Ping.SendAsync and WebRequest.GetResponseAsync. That will require you to follow the async await pattern, but this is an good example of the kind of task this pattern is meant for. In this case you should get rid of all the Dispatcher.Invoke-stuff, since all of your code would run on the UI thread.
The alternative would be to use a timer that runs the tick-event on a threadpool thread, like Timers.Timer. See also timer comparison
I have an async function which still freezes / lags the UI thread for me when I execute it. This is my function calling it.
private void TcpListenerLogic(object sender, string e)
{
Application.Current.Dispatcher.BeginInvoke((Action)async delegate {
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
// Get properties for new anchor
string testInformation = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + results.test_id);
}
}
catch (Exception exception)
{
// Writing some Trace.WriteLine()'s
}
});
}
And this is the async function that freezes my UI Thread
public static async Task<string> getJsonFromURL(string url)
{
try
{
string returnString = null;
using (System.Net.WebClient client = new System.Net.WebClient())
{
returnString = await client.DownloadStringTaskAsync(url);
}
return returnString;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
return null;
}
}
I already tried to make everything in TcpListenerLogic run in a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
}).Start();
Which resulted in the whole UI completely freezing. And I tried to make TcpListenerLogic async and await the dispatcher, which also made everything freeze permanently. I also tried to make TcpListenerLogic async and leave the dispatcher. The dispatcher is only there because I normally have some UI code in there, which I left out for my tests.
I have ventured far through the internet, but no BackgroundWorker, ThreadPool or other methods helped me in my endeavour.
If anyone has help for this particular problem, or a resource that would improve my understanding of async functions in C#, I would much appreciate it.
Edit
As requested a deeper insight in how this event handler is called.
I have System.Net.Websocket, which is connected to the Backend API I am working with and triggers an event, everytime he receives new Data. To guarantee the socket listens as longs as it is open, there is a while loop which checks for the client state:
public event EventHandler<string> TcpReceived;
public async void StartListener(string ip, int port, string path)
{
try
{
using (client = new ClientWebSocket())
{
try
{ // Connect to backend
Uri serverUri = new Uri("ws://" + ip + ":" + port.ToString() + path );
await client.ConnectAsync(serverUri, CancellationToken.None);
}
catch (Exception ex)
{
BackendSettings.IsConnected = false;
Debug.WriteLine("Error connecting TCP Socket: " + ex.ToString());
}
state = client.State;
// Grab packages send in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
try
{
// **Just formatting the received data until here and writing it into the "message" variable**//
TcpReceived(this, message);
// Close connection on command
if (result.MessageType == WebSocketMessageType.Close)
{
Debug.WriteLine("Closing TCP Socket.");
shouldstayclosed = true;
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
break;
}
state = client.State;
}
catch
{
BackendSettings.IsConnected = false;
state = client.State;
}
}
state = client.State;
}
}
catch (Exception ex)
{
// Some error messages and settings handling
}
}
The Event has a handler attached:
TcpReceived += TcpListener_TcpReceived;
And this is the Handler, which calls the previously seen "TcpListenereLogic".
private void TcpListener_TcpReceived(object sender, string e)
{
TcpListenerLogic(sender, e);
//App.Current.Dispatcher.BeginInvoke(new Action(() => {
// TcpListenerLogic(sender, e);
//}));
//new Thread(() =>
//{
// Thread.CurrentThread.IsBackground = true;
// TcpListenerLogic(sender, e);
//}).Start();
}
I previously had the "TcpListenereLogic" as the handler, but I wanted to try different methods to call it. I also left in the commented out part, to show how the call of "TcpListenereLogic" looked already. All my attempts were with all mentioned setups and sadly lead to nothing.
Thank you very much #TheodorZoulias for helping me to find the solution to my problem.
It turns out it wasn't the async function itself, but rather how often it gets called. It got called roughly ~120 times every second.
My solution starts by calling the Listener method over a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
MainWindow.tcpListener.StartListener(ip, portNumber, "/api/");
}).Start();
To limit the amount of calls that happen every second I added a dispatcher timer, that resets a bool after it has been used for a call, by my Event.
readonly System.Windows.Threading.DispatcherTimer packageIntervallTimer =
new System.Windows.Threading.DispatcherTimer();
bool readyForNewPackage = true;
private void ReadyForPackage(object sender, EventArgs e)
{
readyForNewPackage = true;
}
public async void StartListener(string ip, int port, string path)
{
packageIntervallTimer.Interval = TimeSpan.FromMilliseconds(50);
packageIntervallTimer.Tick += (s, e) => { Task.Run(() => ReadyForPackage(s, e)); };
packageIntervallTimer.Start();
Then I wrapped everything inside the while loop into an if condition based on the bool, the most important part was to have my "event EventHandler TcpReceived" in there:
// Grab packages sent in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
if (readyForNewPackage == true)
{
readyForNewPackage = false;
try
{
....
TcpReceived(this, message);
....
}
catch
{
...
}
}
}
I added my TcpListenerLogic to the Eventhandler:
TcpReceived += TcpListenerLogic;
And my TcpListenerLogic now looked like this (names have been changed):
private async void TcpListenerLogic(object sender, string e)
{
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
string testID = "";
if (results.test_id is JValue jValueTestId)
{
testID = jValueTestId.Value.ToString();
}
else if (results.test_id is string)
{
testID = results.test_id;
}
// Get properties for new object
string information = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + testID );
if (information != null)
{
await App.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// Create object out of the json string
TestStatus testStatus = new TestStatus();
testStatus.Deserialize(information);
if (CommunicationCommands.isNameAlreadyInCollection(testStatus.name) == false)
{
// Add new object to the list
CommunicationCommands.allFoundTests.Add(testStatus);
}
}));
{
}
catch (Exception exception)
{
....
}
}
Adding a new Thread to execute any step results in problems, so keep in mind that all this uses the thread created at the beginning for "StartListener"
I'm using a winform to try to gather online/offline status of every IP on the network, doing so I'm using a ping request, if it replies it marks the IP as online then moves on. Only issue is waiting for up to 255 replies, after it gets all 255 responses I am wanting it to fill a data grid view.
I've managed to get it all to work but only downside is, gui hangs while doing this process, I figured just use a separate thread with the following expression
Thread T1 = new Thread(PingHost)
T1.run();
PingHost does as the name implies, pings all the hosts and decides if online or offline. Problem is I tried to update the dgv table from the thread, naturally dgv is locked to main thread.
So I tried switching to a Task and just grab the return value and update after everything is finished. Sadly I can't quite get how to get the return value from the task AND have it run on a separate thread.
I've tried googling different methods, but just running in circles at this point, so I humbly come to you guys for assistance
Code of main thread using tasks
List<string> everything = new List<string>();
int i = 0;
Task<List<string>> task1 = Task<List<string>>.Factory.StartNew(PingHost);
everything = task1.Result;
foreach(var item in everything)
{
var index = dataGridView1.Rows.Add();
dataGridView1.Rows[i].Cells["IP"].Value = item;
i++;
}
And this is the thread of my PingHost method
bool pingable = false;
Ping pinger = null;
int i = 0;
string ip;
while (i < 255)
{
ip = "192.168.0." + i;
try
{
pinger = new Ping();
PingReply reply = pinger.Send(ip, 8);
pingable = reply.Status == IPStatus.Success;
}
catch (PingException)
{
MessageBox.Show("ERROR");
// Discard PingExceptions and return false;
}
finally
{
if (pinger != null)
{
pinger.Dispose();
}
}
if (pingable)
{
checkedIP.Add(ip + ": ONLINE");
}
else
{
checkedIP.Add(ip + ": OFFLINE");
}
i++;
}
return checkedIP;
This might be a bit overkill, but I just drafted a solution. Basically I created a new Class for pinging with an event that triggers after each Ping returned, this event uses custom EventArgs to return the IP that was just pinged and if it is online or not. I then subscribed to that Event in my GUI Thread and just update the GUI. Here's some code:
This is my Pinger class responsible for pinging the actual Computers:
class Pinger
{
public event EventHandler<PingReturnedEventArgs> OnPingReturned;
public void PingNetwork()
{
for (int i = 1; i <= 255; i++)
{
string ip = $"192.168.0.{i}";
Ping ping = new Ping();
try
{
PingReply reply = ping.Send(IPAddress.Parse(ip));
TriggerEvent(reply?.Address.ToString(), true);
}
catch (Exception)
{
TriggerEvent(ip, false);
}
}
}
private void TriggerEvent(string ip, bool online)
{
if (OnPingReturned == null) return;
PingReturnedEventArgs args = new PingReturnedEventArgs(ip, online);
OnPingReturned(this, args);
}
}
My custom EventArgs:
class PingReturnedEventArgs : EventArgs
{
public string Ip { get; private set; }
public bool Online { get; private set; }
private PingReturnedEventArgs() { }
public PingReturnedEventArgs(string ip, bool online)
{
Ip = ip;
Online = online;
}
}
And finally here is how I'm actually using all of this:
Pinger pinger = new Pinger();
pinger.OnPingReturned += Your event handler to update the GUI
// I recommend doing it like this so you can stop the Thread at a later time
// Maybe with like a cancel button
Thread pingThread = new Thread(pinger.PingNetwork);
pingThread.Start();
The event handler looks like this private void PingReturnedHandler(object sender, PingReturnedEventArgs args)
The two main benefits of this are that 1. the GUI Thread remains unblocked, meaning the GUI will still respond to user input and 2. this procedurally (on every ping completion) triggers the event, meaning that if it takes a long time to ping all the PCs you don't have to wait for the entirety to finish before the user sees something
I am trying to get the IP's of devices attached to my network(WLAN to which i am connected) .Firstly i used Command Line in Win8 and pinging there serially while knowing my own IP (incrementing it each time and pinging ) .To get programmatically do it like WnetWatcher I am utilizing Ping Class by calling a function passing attempts=4 and timeout=3 but a blue screen saying PROCESS_HAS_BLOCKED_PAGESand found it an underlying API issue. Anyone has a better idea than this to get all the devices IP's because several threads at SO finds it using Dns Class but that works for a single PC(mine) .
1). What is the laternate of Ping and if it's Ping then how to get around API issue.
2).Also, how can i get the Router IP ,so that I maybe able to run the loop for other IP's on an network or is there any better alternative to it?
public static void Ping(string host, int attempts, int timeout)
{
new Thread(delegate()
{
try
{
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
ping.PingCompleted += new PingCompletedEventHandler(PingCompleted);
ping.SendAsync(host, timeout, host);
}
catch
{
// Do nothing and let it try again until the attempts are exausted.
// Exceptions are thrown for normal ping failurs like address lookup
// failed. For this reason we are supressing errors.
}
}).Start();
}
private static void PingCompleted(object sender, PingCompletedEventArgs e)
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
// Logic for Ping Reply Success
// Console.WriteLine(String.Format("Host: {0} ping successful", ip));
lstlocal.listViewItem //Error ...the intellisense is not accepting it here
}
else
{
// Logic for Ping Reply other than Success
}
}
//function caller code from a button
lstLocal.Items.Clear();
lstLocal.FullRowSelect = true;
bool value;
for (int i = 0; i <= 254; i++)
{
string ping_var = "192.168.1" + "." + i;
value = Ping(ping_var, 4, 3);
// MessageBox.Show("Ping response for"+ping_var +"is" + value);
if(value==true)
{
ListViewItem items=new ListViewItem(ping_var.ToString());
lstLocal.Items.Add(items);
}
}
}
1) You may call SendAsync method of the Ping class instead of Send to avoid blocking:
public void Ping(string host, int attempts, int timeout)
{
for (int i = 0; i < attempts; i++)
{
new Thread(delegate()
{
try
{
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
ping.PingCompleted += new PingCompletedEventHandler(PingCompleted);
ping.SendAsync(host, timeout, host);
}
catch
{
// Do nothing and let it try again until the attempts are exausted.
// Exceptions are thrown for normal ping failurs like address lookup
// failed. For this reason we are supressing errors.
}
}).Start();
}
}
And take care of the ping response in the PingCompleted EventHandler delegate:
private void PingCompleted(object sender, PingCompletedEventArgs e)
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
// Logic for Ping Reply Success
ListViewItem item = new ListViewItem(ip);
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
lstLocal.Items.Add(item);
}));
}
else
{
lstLocal.Items.Add(item);
}
// Logic for Ping Reply Success
// Console.WriteLine(String.Format("Host: {0} ping successful", ip));
}
else
{
// Logic for Ping Reply other than Success
}
}
2) To get your Router IP or gateway:
static string NetworkGateway()
{
string ip = null;
foreach (NetworkInterface f in NetworkInterface.GetAllNetworkInterfaces())
{
if (f.OperationalStatus == OperationalStatus.Up)
{
foreach (GatewayIPAddressInformation d in f.GetIPProperties().GatewayAddresses)
{
ip = d.Address.ToString();
}
}
}
Console.WriteLine(string.Format("Network Gateway: {0}", ip));
return ip;
}
So i have a BW that looks like this:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if ((worker.CancellationPending == true))
{
e.Cancel = true;
return;
}
else
{
worker.ReportProgress(1);
e.Result = PCIsOnline((string)e.Argument);
}
}
PCIsOnline function starts Ping.Send. Everything works fine.
But in some cases i want to stop BW (or stop ping).
I've tryed this:
bw.CancelAsync(); - but that doesnt help me coz APP will never go back to bw_DoWork again to stop. So i there a way to stop ping or bw.
So i can start it again.
Btw for some reason this doesn't helping too.
bw.CancelAsync();
while (!bw.IsBusy)
{
System.Threading.Thread.Sleep(50);
}
Coz its just loops forever. I guess its becoz i Sleep thread, but its a main thread i though that BW thread shouldn't stop. But it seems like it does. I've seen a thread where instead of sleep DoEvents was used but i'm using WPF and it doesn't have it. And i don't realy want to wait ping to finish it's job.
I've read a lot of threads about BW and how to stop but none is helpfull in my case. Coz by the time i send CancelAsync() DoWork allready passed CancellationPending check and will never return there.
PS: Fisrt time i start BW in TextBox_FocusLost even. And want to Stop and Run it again in List_SelectChanged.
ADDED:
public static bool PCIsOnline(string arg)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
try
{
PingReply reply = pingSender.Send(arg, timeout, buffer, options);
if (reply.Status == IPStatus.Success) { return true; }
else { return false; }
}
catch
{
return false;
}
}
ADDED2:
As it was stated in comment before that instead of using BW is better to use SendAsync. Аnd my code now looks like this. But i still don't understand how can i stop SendAsync outside of PCIsOnline function.
public static void PCIsOnline(string arg)
{
Ping pingSender = new Ping();
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
pingSender.SendAsync(arg, timeout, buffer, options);
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
}
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
}
PingReply reply = e.Reply;
HandleReply(reply);
}
So I'm still looking a way to interrupt BW and restart it or a way to stop PingAsync.
The problem is u only send cancel to bw . But u need to send cancel to Ping (SendAsync) too.
Send cancel to Ping
Ping.SendAsyncCancel();
bw.CancelAsync();
Use SendAsync:
public static bool PCIsOnline(string arg)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
try
{
PingReply reply = pingSender.SendAsync(arg, timeout, buffer, options);
if (reply.Status == IPStatus.Success) { return true; }
else { return false; }
}
catch
{
return false;
}
}
Since I can't find a way to stop ping I've decided to ignore ping results if it's not the one I need ATM.
So I just added check in to HandleReply that sends return if that this ping result not longer needed.
private void Name_LostFocus(object sender, System.EventArgs e)
{
var textBox = sender as TextBox;
//No longer Using BW since Ping.SendAsync() does the job
PCIsOnline(textBox.Text);
}
private void Search_SelectChanged(object sender, SelectionChangedEventArgs e)
{
ListBox Search = sender as ListBox;
if (Search.SelectedValue != null)
{
this.OldName.Text = Search.SelectedValue.ToString();
PCIsOnline(this.OldName.Text);
}
}
public void PCIsOnline(string arg)
{
Ping pingSender = new Ping();
//Sending argument to perform check later
pingSender.PingCompleted += (sender1, args) => PingCompletedCallback(sender1, args, arg);
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 5;
pbrTest.Visibility = System.Windows.Visibility.Visible;
pingSender.SendAsync(arg, timeout, buffer, options);
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e, String Current)
{
if (e.Cancelled)
{
HandleReply(null, Current, "Cancelled");
return;
}
if (e.Error != null)
{
HandleReply(null, Current, "Error");
return;
}
PingReply reply = e.Reply;
HandleReply(reply, Current, "");
}
private void HandleReply(PingReply reply, String PC, String msgtype = "")
{
//Ignore old result I only need one that is in OldName textBox
if (PC != this.OldName.Text) { return; }
//Next you should add your result handling
//Happens on a error
if (reply == null)
{
/*do something*/
}
//PC is online
else if (reply.Status == IPStatus.Success)
{
/*do something*/
}
//PC is offline
else
{
/*do something*/
}
}
Not the best way to solve the problem but that's the best I can think of.