Click to See Complete Forum and Search --> : Need a clear definition for what a callback is?


RickyWh
December 21st, 2008, 07:09 PM
Hi again everyone

I've been reading around the internet and learning more and more about this great programming language c#. I often hear the term 'callback' hear and there and I try to find out what exactly it is. However, every time it happens I don't ever get a clear definition.

Can anyone help me out here with a definition and a code example?

RickyWh,

dglienna
December 21st, 2008, 07:11 PM
Google is your friend!

http://www.myelin.co.nz/notes/callbacks/cs-delegates.html

TheCPUWizard
December 21st, 2008, 07:15 PM
delegates are a form of callback.

More specifically a callback is a peice of code that you can tell another peice of code to execute under specific circumstances.

This is useful for creating general purpose solutions where certain operations must be "replacable". The replacable parts are written seperatly

"The general code will call back to the specific code"

RickyWh
December 21st, 2008, 07:48 PM
thanks

darwen
December 22nd, 2008, 04:14 PM
Usually you have a piece of code A which calls function B.

A callback is specified by the caller (i.e. A) which the function which is called then executes e.g.

A calls B specifying C. B calls C (i.e. 'calls back' out) then returns to A.

Darwen.

ZOverLord
December 22nd, 2008, 10:07 PM
Some more detail: http://en.wikipedia.org/wiki/Callback_(computer_science))

RickyWh
December 22nd, 2008, 11:23 PM
Very strange concept, thanks for the help everyone. I'll have to probably see a useful example in order to fully understand it.

TheCPUWizard
December 22nd, 2008, 11:33 PM
Very strange concept, thanks for the help everyone. I'll have to probably see a useful example in order to fully understand it.

Psuedo Code...

LogToFile () { Write Information to a File }
LogToConsole() { Write Information to Console }

void DoWork(CallBack)
{
Some Work
if (Error)
CallBack(ErrorMessage)
}


Now you can:

DoWord(LogToFile); // Will log errors to the file
DoWork(LogToConsole) // Will log Errors to the Console.

Further more you can create additional callbacks later to perform functions which could not possibly have been concieved when DoWork was writter...Then just callDoWork passing the new callback routine.

ZOverLord
December 23rd, 2008, 12:03 AM
Very strange concept, thanks for the help everyone. I'll have to probably see a useful example in order to fully understand it.

Here is an example of getting a web page:

http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx

As you can see, the callback is what is called when the web page request completes in this example ("You make a request to get a web page like for example, http://google.com") , if it completes, your request is now a response, containing the contents of the http://google.com web page. If it takes too long, the the timer cancels the request, in this case.

Example. If your request to read http://google.com finishes before the timer expires, then your callback is what is called when the web page read request completes in this case, meaning you now have a response to your request. The response would be the http://google.com web page ("You will need to change the example below to point to a real web site, such as Google.").

So, you are not waiting for this response, your program can do other things and if and when the repsonse is received what you passed to be called, will be called when and if that happens, in this case, if it is before 2 minutes, otherwise, the timer fires, and the original request is cancelled.

using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;


public class RequestState
{
// This class stores the State of the request.
const int BUFFER_SIZE = 1024;
public StringBuilder requestData;
public byte[] BufferRead;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamResponse;
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
requestData = new StringBuilder("");
request = null;
streamResponse = null;
}
}

class HttpWebRequest_BeginGetResponse
{
public static ManualResetEvent allDone= new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
const int DefaultTimeout = 2 * 60 * 1000; // 2 minutes timeout

// Abort the request if the timer fires.
private static void TimeoutCallback(object state, bool timedOut) {
if (timedOut) {
HttpWebRequest request = state as HttpWebRequest;
if (request != null) {
request.Abort();
}
}
}

static void Main()
{

try
{
// Create a HttpWebrequest object to the desired URL.
HttpWebRequest myHttpWebRequest= (HttpWebRequest)WebRequest.Create("http://www.contoso.com");


/**
* If you are behind a firewall and you do not have your browser proxy setup
* you need to use the following proxy creation code.

// Create a proxy object.
WebProxy myProxy = new WebProxy();

// Associate a new Uri object to the _wProxy object, using the proxy address
// selected by the user.
myProxy.Address = new Uri("http://myproxy");


// Finally, initialize the Web request object proxy property with the _wProxy
// object.
myHttpWebRequest.Proxy=myProxy;
***/

// Create an instance of the RequestState and assign the previous myHttpWebRequest
// object to its request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;


// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);

// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true);

// The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne();

// Release the HttpWebResponse resource.
myRequestState.response.Close();
}
catch(WebException e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("\nMessage:{0}",e.Message);
Console.WriteLine("\nStatus:{0}",e.Status);
Console.WriteLine("Press any key to continue..........");
}
catch(Exception e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("Source :{0} " , e.Source);
Console.WriteLine("Message :{0} " , e.Message);
Console.WriteLine("Press any key to continue..........");
Console.Read();
}
}
private static void RespCallback(IAsyncResult asynchronousResult)
{
try
{
// State of request is asynchronous.
RequestState myRequestState=(RequestState) asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest=myRequestState.request;
myRequestState.response = (HttpWebResponse) myHttpWebRequest.EndGetResponse(asynchronousResult);

// Read the response into a Stream object.
Stream responseStream = myRequestState.response.GetResponseStream();
myRequestState.streamResponse=responseStream;

// Begin the Reading of the contents of the HTML page and print it to the console.
IAsyncResult asynchronousInputRead = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch(WebException e)
{
Console.WriteLine("\nRespCallback Exception raised!");
Console.WriteLine("\nMessage:{0}",e.Message);
Console.WriteLine("\nStatus:{0}",e.Status);
}
allDone.Set();
}
private static void ReadCallBack(IAsyncResult asyncResult)
{
try
{

RequestState myRequestState = (RequestState)asyncResult.AsyncState;
Stream responseStream = myRequestState.streamResponse;
int read = responseStream.EndRead( asyncResult );
// Read the HTML page and then print it to the console.
if (read > 0)
{
myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read));
IAsyncResult asynchronousResult = responseStream.BeginRead( myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
Console.WriteLine("\nThe contents of the Html page are : ");
if(myRequestState.requestData.Length>1)
{
string stringContent;
stringContent = myRequestState.requestData.ToString();
Console.WriteLine(stringContent);
}
Console.WriteLine("Press any key to continue..........");
Console.ReadLine();

responseStream.Close();
}

}
catch(WebException e)
{
Console.WriteLine("\nReadCallBack Exception raised!");
Console.WriteLine("\nMessage:{0}",e.Message);
Console.WriteLine("\nStatus:{0}",e.Status);
}
allDone.Set();

}

cilu
December 23rd, 2008, 01:39 AM
Very strange concept, thanks for the help everyone. I'll have to probably see a useful example in order to fully understand it.
Here are some examples (more) (don't necessary think .NET):

1. Suppose you wrote a function that is able to sort a container. But that container can sort integers, doubles, strings or foos. How do you make the comparison between the elements? Well, if you had another function that can take two elements and compare them, then you can pass this comparison function to the sorting function, and the sort function will call it back, each time it needs to compare two elements. And then you can have one callback function for each comparison.

2. Suppose you want to find an element in a container. And let's suppose it's not just integers or strings, but complex types, like Employee. You need to find an employee by ID, or by Name or perhaps by something else. If you had functions that take an Employee and returns a bool, one comparing the ID with something, another the Name, etc, then you can use these functions (let's call them predicates) as arguments to another general function that iterates over the elements of the container, and each time it needs to compare it calls back on the predicate. You can then use the general search function with a specific predicate (call back function) depending on your needs.