Solved

Threadpool and Callbacks

Posted on 2011-03-20
2
934 Views
Last Modified: 2012-05-11
Hi

could someone please point me to some simple code on threadpools and callbacks. The more I read on a google search, the more confused I get. I am a moderate level programmer at best, so easily confused unless it is kept simple.

I want to go off and get some external data, using a callback when the data comes back, multiple calls for different data simultaneously. Therefore, I believe what I need to use is a threadpool call with a callback that tells me when the request is responded to, such that I can then run a process to process the data being returned from the request, and such that the processor moves on whilst waiting for the response to come back.

I would appreciate it if I could be pointed to some simple code that creates a threadpool request to a method, passes parameters to the method, and allows processing of the resulting data that comes back.

I can't seem to find a simple code example to achieve same. I am doing this in another application with the backgroundworker, but believe I need to move to a threadppol here as there will be multiple requests happening simultaneously with differing response and process times. My application is a simple c# wondows application, although I am looking to do tihs with a c# console application to maximise speed.

Any advice would be appreciated

Ian
0
Comment
Question by:z488758
2 Comments
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 500 total points
ID: 35180957
I'm not sure this will be helpful or not, I just happened to have it handy.

It uses a ThreadPool thread to do the ping'ing of IP addresses, and once a list of IP's that responded to the ping has been made, I used Dns.BeginGetHostEntry, which is an asynchronous method call and depends on the use of callbacks to notify me of completion.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;

class Program
{
	static long completedCounter = 0;
	static long errorCounter = 0;
	static long successCounter = 0;

	static object listLock = new object();
	static object consoleLock = new object();

	static List<IPAddress> aliveHosts = new List<IPAddress>();

	static void Main(string[] args)
	{
		Console.Write("Finding alive hosts...");

		// This just pings .1 through .254, for each network
		// 192.168.1.x, 192.168.2.x, 192.168.3.x and 192.168.4.x
		// This is my entire network, I can't make a test bigger'n this. ;)
		// Everytime a host responds to a ping, add it's address to
		// the aliveHosts list
		for (byte i = 1; i < 5; i++)
		{
			for (byte j = 1; j < 255; j++)
			{
				IPAddress ip = new IPAddress(new byte[] { 192, 168, i, j });
				ThreadPool.QueueUserWorkItem(PingProc, ip);
			}
		}

		do
		{
			Thread.Sleep(0);
		} while (Interlocked.Read(ref completedCounter) < 1016);

		// Reset the completedCounter
		completedCounter = 0;

		// Start timer here to check DNS performance
		Stopwatch stopwatch = new Stopwatch();
		stopwatch.Start();

		foreach (IPAddress ip in aliveHosts) // Only do lookups for hosts that are currently up
		{
			// Call GetHostEntry asynchronously - when GetHostEntry
			// finishes our GetHostEntryCallback method will be called
			Dns.BeginGetHostEntry(ip, new AsyncCallback(GetHostEntryCallback), ip);
		}

		do
		{
			// Wait until all pending GetHostEntry's finished
			// Thread.Sleep(0) won't sleep the thread, but will yield
			// processor time if another thread needs it
			Thread.Sleep(0);
		} while (Interlocked.Read(ref completedCounter) < aliveHosts.Count);
		stopwatch.Stop();

		Console.WriteLine("Resolved {0} IP addresses in {1} seconds.", aliveHosts.Count, stopwatch.Elapsed.TotalSeconds);
		Console.WriteLine("{0} IP addresses successfully resolved, {1} failed.", successCounter, errorCounter);
		Console.ReadKey();
	}

	static void PingProc(object arg)
	{
		IPAddress ip = (IPAddress)arg;
		Ping ping = new Ping();
		if (ping.Send(ip, 50).Status == IPStatus.Success)
			lock (listLock) aliveHosts.Add(ip); // This lock prevents different threads from trying to update the list at the same time
		Interlocked.Increment(ref completedCounter);
		lock (consoleLock) // This lock prevents threads from trying to write to the console at the same time
		{
			Console.CursorLeft = 22;
			Console.Write("{0} of 1016", Interlocked.Read(ref completedCounter));
		}
	}

	static void GetHostEntryCallback(IAsyncResult iar)
	{
		string hostName = null;
		try
		{
			IPHostEntry host = Dns.EndGetHostEntry(iar); // Gets the result of the asynchronous method
			hostName = host.HostName;
			Interlocked.Increment(ref successCounter);
		}
		catch (Exception ex)
		{
			hostName = ex.Message;
			Interlocked.Increment(ref errorCounter);
		}
		finally
		{
			lock (consoleLock) Console.WriteLine("{0} -> {1}", iar.AsyncState, hostName);
		}
		Interlocked.Increment(ref completedCounter); // Increment the counter everytime a lookup is done (success or failure)
		return;
	}
}

Open in new window



The "Begin..." methods are common in the .Net Framework, and you can use a similar methodology for your own methods - you just assign the function to a delegate, then you can call BeginInvoke on the delegate to execute your code in the background:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;

namespace ConsoleApplication2
{
	class Program
	{
		delegate string MyFuncDelegate(string message);

		static string modifiedMessage;

		static void Main(string[] args)
		{
			MyFuncDelegate myFuncVar = new MyFuncDelegate(MyFuncImplementation);

			// Start the function in background
			IAsyncResult iar = myFuncVar.BeginInvoke("Hello World", MyFuncCallback, myFuncVar);

			// Wait for it to finish
			iar.AsyncWaitHandle.WaitOne();

			Console.WriteLine(modifiedMessage);
			Console.ReadKey();
		}

		static string MyFuncImplementation(string Message)
		{
			return Message.ToUpper();
		}

		static void MyFuncCallback(IAsyncResult iar)
		{
			MyFuncDelegate originallyExecutedFunc = (MyFuncDelegate)iar.AsyncState;

			modifiedMessage = originallyExecutedFunc.EndInvoke(iar);

			// Often the above will be written more succinctly as:
			//modifiedMessage = ((MyFuncDelegate)iar.AsyncState).EndInvoke(iar);
		}
	}
}

Open in new window

0
 

Author Closing Comment

by:z488758
ID: 35186787
Thanks, appreciate the assistance, will try and work with this
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
rest webservice call over https via c# 6 37
C# Comparing String Arrays. 5 39
C# Object Reference is Required for the non-static field, method, or property 10 32
Hey!! 5 33
Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question