?
Solved

Threadpool and Callbacks

Posted on 2011-03-20
2
Medium Priority
?
955 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
2 Comments
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 1500 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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …

770 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