0

I'am using WPF with multi threading. Problem is during execution of the MAIN thread hangs, like its waiting for something or infinite loop in main UI. I don't know if there's any other approach when it comes to multi threading in WPF. See my code below:

Thread myNewThread1 = new Thread(() => ping(IP1, img_m));
Thread myNewThread2 = new Thread(() => ping(IP2, img_h));
Thread myNewThread3 = new Thread(() => ping(IP3, img_c));
Thread myNewThread4 = new Thread(() => ping(IP4, img_b));
Thread myNewThread5 = new Thread(() => ping(IP5, img_e));

myNewThread1.Start();
myNewThread2.Start();
myNewThread3.Start();
myNewThread4.Start();
myNewThread5.Start();


private void ping(string IP, Image img)
{
    this.Dispatcher.Invoke(() =>
    {
        Ping p = new Ping();
        var r = p.Send(IP, 1000, new byte[5]);

        if (r.Status == IPStatus.Success)
        {
            var image = new BitmapImage();

            image.BeginInit();
            image.UriSource = new Uri("subonline.gif", UriKind.Relative);
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.EndInit();
            ImageBehavior.SetAnimatedSource(img, image);
        }
        else
        {
            var image = new BitmapImage();

            image.BeginInit();
            image.UriSource = new Uri("suboffline.gif", UriKind.Relative);
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.EndInit();
            ImageBehavior.SetAnimatedSource(img, image);
        }
    });

    Thread.Sleep(500);
    ping(IP, img);
}    
4
  • use BackgroundWorker Commented Mar 1, 2017 at 5:52
  • Instead of using threads (or any other selfmade background processing), better take a look at PingAsync and PingCompleted. Commented Mar 1, 2017 at 6:54
  • HI guys thanks for your reply i switch to backgroundworker and its working fine now :) Commented Mar 1, 2017 at 7:11
  • @NikhilAgrawal BackgroundWorker is very obsolete approach, and you should avoid it. Commented Mar 1, 2017 at 13:20

2 Answers 2

1

Your main thread hangs because of Dispatcher.Invoke wrong usage, it should be used for UI logic only, so you should move out the Ping-oriented logic out of it.

Do not use the BackgroundWorker for this, it's an obsolete and heavy construction you don't really need. Also, do not a thread for pinging, this is wrong approach, and that's why:

Pinging operation is network-related, and the thread you're using for wait the remote server to response simply wastes the system resources, as it does absolutely nothing except wait. So you should switch to asynchronous approach for this.

You either should subscribe to Ping.PingCompleted event and call the SendAsync method, like this:

private void ping(string IP, MediaTypeNames.Image img)
{
    Ping p = new Ping();
    PingReply r;
    // lambda delegate here, may use event handler instead
    p.PingCompleted += (sender, args) => { PingCompleted(args, img); };
    r = p.SendAsync(IP, 1000, new byte[5], null);
}

private void PingCompleted(PingCompletedEventArgs args, MediaTypeNames.Image img)
{
    this.Dispatcher.Invoke(() =>
        {
            string imageAddress;
            if (args.Reply.Status == IPStatus.Success)
            {
                imageAddress = "subonline.gif";
            }
            else
            {
                imageAddress = "suboffline.gif";
            }

            var image = new BitmapImage();
            image.BeginInit();
            image.UriSource = new Uri(imageAddress, UriKind.Relative);
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.EndInit();
            ImageBehavior.SetAnimatedSource(img, image);
        });
}

or you should use async/await feature which was introduced exactly for such cases (code partially from this answer):

// async event handler
private async void btn_Click(object sender, EventArgs e)
{
    // async call to all the ips
    var results = await PingAsync(new List<string> { IP1, IP2, IP3, IP4, IP5 });
    // here we do not need the Dispatcher as await will restore UI context for you
   PingCompleted(results[0], img_m);
   // etc
}

private void PingCompleted(PingReply r, MediaTypeNames.Image img)
{
    string imageAddress;
    if (r.Status == IPStatus.Success)
    {
        imageAddress = "subonline.gif";
    }
    else
    {
        imageAddress = "suboffline.gif";
    }

    var image = new BitmapImage();
    image.BeginInit();
    image.UriSource = new Uri(imageAddress, UriKind.Relative);
    image.CacheOption = BitmapCacheOption.OnLoad;
    image.EndInit();
    ImageBehavior.SetAnimatedSource(img, image);
}

// helper method
private async Task<PingReply[]> PingAsync(List<string> theListOfIPs)
{
    Ping pingSender = new Ping();
    var tasks = theListOfIPs.Select(ip => pingSender.SendPingAsync(ip, 1000, new byte[5]));
    return await Task.WhenAll(tasks);
}
Sign up to request clarification or add additional context in comments.

Comments

0

Do not include the call to p.Send method in the dispatcher - currently only the Thread.Sleep(500) is done in the background and everything else is done in the UI thread.

Also, I believe that because of the Thread.Sleep the function never gives the UI thread a chance to work so the pinging never occurs. Replace the use of Thread.Sleep with a Thread.Timer object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.