Asynchronous Programming - HELP! - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Asynchronous Programming - HELP!

hv79hv79 Posts: 1Member
Hello all,

I've been searching all day (literally), in dozens of recommended textbooks, all over the internet,etc., for a simple, straightforward explanation of how to use delegates for asynchronous programming. All of the examples are long, complex, or do not explain the concept in a simple, easy to understand manner.

Can anyone please provide a super-simple program that explains how these work? I'm starting to think I may never understand the concepts of delegates clearly, and will thus never be able to use them for asynchronous programming...

Thanks in advance for your help and suggestions!

Comments

  • iwilld0itiwilld0it Posts: 1,134Member
    To start a delegate is nothing but a class wrapper around function pointers.

    Here is my Async demo. Basically, it fires off a Async function that waits 3 seconds and then returns a message.

    Basically I created a windows project and dragged a button onto surface. I removed generated comments and region to unclutter the code.

    [code]
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;

    using System.Runtime.Remoting.Messaging;

    namespace CSAsynch
    {
    // This is my custom delegate.
    [b]public delegate string MyAsyncMessage()[/b];

    public class Form1 : System.Windows.Forms.Form
    {
    private System.Windows.Forms.Button button1;
    private System.ComponentModel.Container components = null;
    private MyAsyncMessage myCallBack;

    public Form1()
    {
    InitializeComponent();
    [b]myCallBack += new MyAsyncMessage(AsyncMessageFunc);[/b]
    }

    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null)
    {
    components.Dispose();
    }
    }
    base.Dispose( disposing );
    }

    private void InitializeComponent()
    {
    this.button1 = new System.Windows.Forms.Button();
    this.SuspendLayout();
    this.button1.Location = new System.Drawing.Point(24, 80);
    this.button1.Name = "button1";
    this.button1.TabIndex = 0;
    this.button1.Text = "button1";
    this.button1.Click += new System.EventHandler(this.button1_Click);
    this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    this.ClientSize = new System.Drawing.Size(292, 273);
    this.Controls.Add(this.button1);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false);
    }

    [STAThread]
    static void Main()
    {
    Application.Run(new Form1());
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
    [b]myCallBack.BeginInvoke(new AsyncCallback(AsyncHandler), myCallBack);[/b]
    button1.Enabled = false;
    // Continue to do other things.
    }

    // This gets called during BeginInvoke method call of our delegate.
    [b]private void AsyncHandler(IAsyncResult ar)
    {
    // Upcast our result.
    AsyncResult result = ar as AsyncResult;

    // We passed our delegate as second argument to BeginInvoke.
    MyAsyncMessage cb = ar.AsyncState as MyAsyncMessage;

    // This finishes are async call.
    // EndInvoke will have the return value.
    MessageBox.Show(cb.EndInvoke(ar));

    button1.Enabled = true;
    }

    // This is our call function that gets called Asyncronously
    private string AsyncMessageFunc()
    {
    // Wait 3 seconds to simulate work.
    System.Threading.Thread.Sleep(3000);

    // Show message to indicate that Async call is finished.
    return "Hi There!";
    }[/b]
    }
    }
    [/code]

    First off, I created a delegate (function pointer):

    [code]
    public delegate string MyAsyncMessage();
    [/code]

    This function pointer can point to any function that accepts no arguments and returns a string.

    In this line:

    [code]
    myCallBack += new MyAsyncMessage(AsyncMessageFunc);
    [/code]

    We are stating that we want the function pointer to point to the AsyncMessageFunc function, which so happens to accept no arguments and returns a string. From here on, myCallBack is an alias for AsyncMessageFunc.

    Now, comes the async part. When a delegate class is generated, three methods are generated for the class:

    Invoke()
    BeginInvoke()
    EndInvoke()

    Invoke() is basically the syncronous call and will contain the same arguments and return value that your aliased functions contain.

    BeginInvoke() is the same as Invoke() accept it begins an asynchronous call and accepts extra arguments for passing a AsyncCallback delegate (another call back) and generic data.

    The EndInvoke() function must be called after the asyncronous call finishes and will contain the return value of our aliased function.

    In the example, I used the strategy of initiating the the async call and passing the custom delegate as the generic data object:

    [code]
    myCallBack.BeginInvoke(new AsyncCallback(AsyncHandler), [b]myCallBack[/b]);
    [/code]

    I do this, because it makes it easier to call EndInvoke() later. However, you can pass any custom class object as the second argument.

    The AsyncCallback delegate is a .NET callback that you must register when making asynch calls. It gets called when your function is finished. In this example, we alias AsyncHandler to be called-back.

    Inside AsyncHandler:

    [code]
    // This gets called during BeginInvoke method call of our delegate.
    private void AsyncHandler(IAsyncResult ar)
    {
    // Upcast our result.
    AsyncResult result = ar as AsyncResult;

    // We passed our delegate as second argument to BeginInvoke.
    MyAsyncMessage cb = ar.AsyncState as MyAsyncMessage;

    // This finishes are async call.
    // EndInvoke will have the return value.
    MessageBox.Show(cb.EndInvoke(ar));

    button1.Enabled = true;
    }
    [/code]

    An IAsyncResult object gets passed. We upcast it to AsyncResult object, which has properties that describe the async call. The AsyncState property contains the object that was passed as the last argument of BeginInvoke(). In our case it was our MyAsyncMessage delegate. Finally, we call EndInvoke() on the delegate, which in this case displays the message that AsyncMessageFunc() returns (because cb is essentially an alias for AsyncMessageFunc.)

    Finally, the function that is called-back async ...

    [code]
    // This is our call function that gets called Asyncronously
    private string AsyncMessageFunc()
    {
    // Wait 3 seconds to simulate work.
    System.Threading.Thread.Sleep(3000);

    // Show message to indicate that Async call is finished.
    return "Hi There!";
    }
    [/code]

    The code pauses for 3 seconds to simulate work and then returns a message.

    Essentially, while this function is being called async, you can do other things in the user interface etc ...

    As a final note, an async call is nothing more than calling your function on a separate thread. However, instead of going through the trouble of creating a thread and starting a hread, you are using a delegate, that handles all the details for you.





Sign In or Register to comment.