0

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;
        }
user838691
  • 320
  • 1
  • 5
  • 13
  • 2
    That's how `DispatcherTimer` works (with default dispatcher... and default dispatcher is ... drums ... UI dispatcher ) – Selvin Dec 07 '22 at 11:54
  • Use view model ... which should register for messages (some publish subscribe implementation) ... start service which would do checks in the background and publish state ... if view model receive message it changes some properties (fx IsConnected) ... then use binding to do what you do in `Dispatcher.Invoke` – Selvin Dec 07 '22 at 12:00
  • 1
    Also note that it is pointless to use Dispatcher.Invoke in the Tick handler of a DispatcherTimer. However, since you already have that, and CanConnectToTheInternet seems to be blocking, just use a System.Threading.Timer (which runs on a background thread) instead of DispatcherTimer. – Clemens Dec 07 '22 at 12:03
  • @Clemens: thanks, i'll try Threading timer instead of Dispatch timer. – user838691 Dec 07 '22 at 12:16

1 Answers1

1

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

JonasH
  • 28,608
  • 2
  • 10
  • 23