Event Callbacks in Java

Event callbacks in Java (including Android) are supported starting in v9.5.0.52. To receive event callbacks, first create a Java class derived from one of the Chilkat event callback classes. The event callback classes are: CkBaseProgress, CkHttpProgress, CkZipProgress, CkFtp2Progress, CkMailManProgress, CkTarProgress, and CkSFtpProgress.

All future Chilkat classes will only use CkBaseProgress. Theses event callback classes will be documented in the “Events” section of each class’s online reference documentation.

Here is an example of an HTTP download using event callbacks in Java. First we have the MyHttpProgress derived from CkHttpProgress. Following that, we have the simple Java program that installs the event handler and does the HTTP download. Event callbacks will also happen with the asynchronous version of the methods, but beware of the fact that when asynchronous, the task is running in a background thread and the callback occurs in the background thread.

import com.chilkatsoft.CkHttpProgress;
import com.chilkatsoft.CkTask;


public class MyHttpProgress extends CkHttpProgress 
{	
  public boolean AbortCheck()
  	{
      System.out.println("AbortCheck");
      // Return true to abort, false to allow the method to continue.
      return false;
  	}
  	
  // pctDone is a value from 0 to 100
  // (it is actually value from 0 to the PercentDoneScale property setting)
  public boolean PercentDone(int pctDone)
  {
    System.out.println(pctDone);
    // Return true to abort, false to allow the method to continue.
    // Note: A PercentDone event is the equivalent of an AbortCheck.  
    // When PercentDone events are frequently firing, AbortCheck events are suppressed.
    // AbortCheck events will fire when the time between PercentDone events is longer 
    // than the HeartbeatMs property setting.
    return false;
  }
  
  public void ProgressInfo(String name, String value)
  {
    System.out.println(name + ": " + value);
  }
  
  public void TaskCompleted(CkTask task)
  {
     System.out.println("task completed!");
  }
  
  }

The synchronous Java program w/ event callbacks… (the asynchronous version follows..)

import com.chilkatsoft.CkHttp;

public class HttpWithEvents {
	
  static {
    try {
    	
    	System.loadLibrary("chilkat");
    	
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }


	
  public static void main(String argv[])
  	{
    CkHttp http = new CkHttp();
    
    // Install an event callback handler to get progress events.
    MyHttpProgress myProgress = new MyHttpProgress();
    http.put_EventCallbackObject(myProgress);
    
    boolean success;

    //  Any string unlocks the component for the 1st 30-days.
    success = http.UnlockComponent("Anything for 30-day trial");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }

    //  Download a file at a URL.
    success = http.Download("http://www.chilkatsoft.com/download/9.5.0.51/ChilkatDotNet45-9.5.0-x64.zip","ChilkatDotNet45-9.5.0-x64.zip");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }
    
    System.out.println("OK");
  	}
  }

The asynchronous Java program w/ event callbacks…

import com.chilkatsoft.CkHttp;
import com.chilkatsoft.CkTask;

public class AsyncHttp {
	
  static {
    try {
    	
    	System.loadLibrary("chilkat");
    	
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }


	
  public static void main(String argv[])
  	{
    CkHttp http = new CkHttp();
    
    // Install an event callback handler to get progress events.
    MyHttpProgress myProgress = new MyHttpProgress();
    http.put_EventCallbackObject(myProgress);
    
    boolean success;

    //  Any string unlocks the component for the 1st 30-days.
    success = http.UnlockComponent("Anything for 30-day trial");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }

    //  Download a file at a URL.
    CkTask task = http.DownloadAsync("http://www.chilkatsoft.com/download/9.5.0.51/ChilkatDotNet45-9.5.0-x64.zip","ChilkatDotNet45-9.5.0-x64.zip");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }
    
    task.put_UserData("chilkatDotNet45");
    
    if (!task.Run()) {
        System.out.println(task.lastErrorText());
        return;
	}
  
    System.out.println("OK, task is running...");
    
    // Wait a max of 10 seconds for it to finish.
    success = task.Wait(10000);
    
    // What is the task status?
    System.out.println("task status = " + task.status());
  	}
  }

VB.NET TaskCompleted Event for Asynchronous Method Call

Demonstrates a TaskCompleted event for an asynchronous Chilkat method call.
The event callback occurs in the background thread, and therefore any updates to the UI must
happen on the UI thread. For this reason, MethodInvoker is used to make updates to a TextBox..

    Dim WithEvents http As New Chilkat.Http()

    Private Sub http_OnTaskCompleted(sender As Object, args As Chilkat.TaskCompletedEventArgs) Handles http.OnTaskCompleted

        Dim task As Chilkat.Task = args.Task

        ' This event callback is running in the background thread.
        ' To update a UI element, we must be on the UI thread..
        Me.Invoke(New MethodInvoker(
           Sub()
               ' The task.UserData can be used to identify the particular asynchronous method call
               ' that this callback belongs to.
               If (task.UserData = "chilkatHomePage") Then
                   ' An asychronous method is simply calling the corresponding synchronous method
                   ' in a background thread.  In this case, it is a call to QuickGetStr,
                   ' which returned a string, or it returned Nothing for failure.  This result is available
                   ' via task.GetResultString.  The LastErrorText for the background call 
                   ' is available in task.ResultErrorText
                   Dim htmlPage As String = task.GetResultString()
                   If (htmlPage Is Nothing) Then
                       TextBox1.Text = task.ResultErrorText
                   Else
                       TextBox1.Text = htmlPage
                   End If
               End If
           End Sub))
    End Sub

    Private Sub AsyncToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AsyncToolStripMenuItem.Click

        http = New Chilkat.Http()

        Dim task As Chilkat.Task = http.QuickGetStrAsync("http://www.chilkatsoft.com/")
        If (task Is Nothing) Then
            TextBox1.Text = http.LastErrorText
            Exit Sub
        End If

        ' We can set the task.UserData property to identify this particular asynchronous call in the callback.
        task.UserData = "chilkatHomePage"

        ' Start the task in a background thread
        Dim success As Boolean = task.Run()
        If (Not success) Then
            TextBox1.Text = task.LastErrorText
            Exit Sub
        End If

    End Sub

Delphi TaskCompleted Event (using the Chilkat ActiveX)

Demonstrates the TaskCompleted event callback using the Chilkat Delphi ActiveX:

procedure TForm1.httpProgressInfo(ASender: TObject;  const name: WideString; const value: WideString);

begin
    // This event callback occurs in the background thread (because the asynchronous
    // version of the QuickGetStr method was called (i.e. QuickGetStrAsync)
    // UI elements must be updated from the main UI thread...
    TThread.Synchronize(nil, procedure begin
      Memo1.Lines.Add(name + ': ' + value);
      end);

end;

procedure TForm1.httpTaskCompleted(ASender: TObject;  const task: IChilkatTask);
begin
    // This event callback occurs in the background thread (because the asynchronous
    // version of the QuickGetStr method was called (i.e. QuickGetStrAsync)
    // UI elements must be updated from the main UI thread...
    TThread.Synchronize(nil, procedure begin
      Memo1.Lines.Add(task.ResultErrorText);
      end);

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  http: TChilkatHttp;
  success: Integer;
  html: WideString;
  task: IChilkatTask;

begin
  http := TChilkatHttp.Create(Self);

  success := http.UnlockComponent('anything for 30-day trial');
  if (success <> 1) then
  begin
    Memo1.Lines.Add(http.LastErrorText);
    Exit;
  end;

  http.OnTaskCompleted := httpTaskCompleted;
  http.OnProgressInfo := httpProgressInfo;

  // Create a task to do the HTTP GET asynchronously.
  task := http.QuickGetStrAsync('http://www.chilkatsoft.com/');

  // Start the task in a background thread.
  task.Run();

  // Warning: If an event callback method calls TThread.Synchronize, then a call to task.Wait will hang
  // for the full duration of the timeout specified.  (If the wait-forever value of 0 is passed
  // to task.Wait, then it will hang forever.) This is because the call to TThread.Synchronize is waiting
  // for the main thread's event loop.  Control is not returned to the main event loop until this
  // TForm1.Button2Click returns -- thus there is a deadlock. There is no deadlock when a program
  // Waits on a task and there are no event callbacks that call TTHread.Synchronize.
  //task.Wait(5000);

end;

C# TaskCompleted Event — Updating the UI from a Background Thread

This sample C# snippet demonstrates how to use the TaskCompleted event to be notified when an asynchronous method completes. Given that the event callback is in the background thread, any UI updates must occur on the main thread. This example demonstrates how to do it:

	private void taskCompletedToolStripMenuItem_Click(object sender, EventArgs e)
	    {
	    // Demonstrate an asynchronous Chilkat method call with a TaskCompleted event.
	    Chilkat.Http http = new Chilkat.Http();

	    http.OnTaskCompleted += http_OnTaskCompleted;

	    Chilkat.Task task = http.QuickGetStrAsync("http://www.chilkatsoft.com/");

	    // We can set the task.UserData property to identify this particular asynchronous call in the callback.
	    task.UserData = "chilkatHomePage";

	    // Runs the HTTP GET asynchronously on a background thread..
	    task.Run();
	    }

	// This event fires in the background thread. 
	// 
	void http_OnTaskCompleted(object sender, Chilkat.TaskCompletedEventArgs args)
	    {
	    Chilkat.Task task = args.Task;

	    // This event callback is running in the background thread.
	    // To update a UI element, we must be on the UI thread..
	    this.Invoke((MethodInvoker)delegate
		{
		    // The task.UserData can be used to identify the particular asynchronous method call
		    // that this callback belongs to.
		    if (task.UserData.Equals("chilkatHomePage"))
			{
			// An asychronous method is simply calling the corresponding synchronous method
			// in a background thread.  In this case, it is a call to QuickGetStr,
			// which returned a string, or it returned Nothing for failure.  This result is available
			// via task.GetResultString.  The LastErrorText for the background call 
			// is available in task.ResultErrorText
			string htmlPage = task.GetResultString();
			if (htmlPage == null)
			    {
			    textBox2.Text = task.ResultErrorText;
			    }
			else
			    {
			    textBox2.Text = htmlPage;
			    }
			}
		});
	    }
	}

Chilkat v9.5.0.52 – Asynchronous for all Classes in all Programming Languages

Starting in Chilkat v9.5.0.52, asynchronous capability is added across all classes and all programming languages. The new Task and TaskChain classes have been added.

To Beta test, send email to support@chilkatsoft.com. Please specify the programming language, operating system, etc. that is needed.

The online reference documentation has been updated. Examples will be forthcoming. Version 9.5.0.52 will be released later this month.

The existing async functionality in Http, Ftp2, Socket, and Upload will become deprecated and will eventually be removed. Deprecated functionality will be removed in a future 9.6.0 release, where the ActiveX will have new CLSID’s, and a new CreateObject name (with 9_6_0) in the name so as to be able to coexist with the 9_5_0_* ActiveX’s. This will not happen for quite some time (months from now or early 2016).

Cocoa Asynchronous Methods and Event Callbacks

Chilkat v9.3.0 for Cocoa now includes the asynchronous functionality and event callback functionality that has been available in the C++ libs.

Asynchronous methods run in a background thread such that the call immediately returns to the application.  Events are not fired w/ asynchronous method calls — your app would periodically check to see if the background task is finished.

To implement an event callback, your app would define/implement a class that inherits from one of the Cko*Progress base classes.  You provide method implementations to override the methods specified in the Cko*Progress classes (see the header files).  The callback object is specified via the EventCallbackObject property.  For example:

// property setter: EventCallbackObject
– (void)setEventCallbackObject: (CkoFtp2Progress *)eventObj;

Background Enabled Methods – Using Chilkat Asynchronously

Notice: The functionality described here is deprecated and replaced by a newer model for asynchronous method calls. The newer model was introduced in Chilkat v9.5.0.52, and is identified by methods having names ending in “Async” which return a task object.

The Chilkat HTTP component has a set of methods and properties that allow already-existing methods to be called asynchronously. For example, by setting the UseBgThread property equal to True, any background-enabled method, such as Download, will run in a background thread. Normally, when called synchronously, the method returns control to the caller only after the HTTP operation has completed. However, when UseBgThread = True, the method returns immediately and the HTTP operation is started in a background thread. (For a given HTTP object instance, only one background method may be ongoing at a time. It is possible to use multiple HTTP object instances, each of which might be processing a backgrounded method call.)

The set of background-enabling methods and properties are:

  • (property) UseBgThread – If True, then background-enabled methods will run in a background thread. Normally, a method will return after its work is completed. However, when UseBgThread is true, the method will return immediately and a background thread is started to carry out the method’s task.
  • (property) BgTaskRunning – If True then the object instance already has a backgrounded method running. Another backgrounded method cannot be started until the 1st completes. (Multiple simultaneous background methods may run by using multiple object instances.)
  • (property) BgTaskFinished – Becomes True when the background method completes. Your application would periodically check for this condition.
  • (property) BgTaskSuccess – Only meaningful (True/False) after a background method completes.
  • (property) BgLastErrorText – Last-error information is saved here and not in the LastErrorText property. If the background method fails, this will contain information about what transpired. (This property also contains information when the background method succeeds.)
  • (method) BgTaskAbort – Call this to force the currently running backgrounded method to abort.
  • (property) BgResultString – If the backgrounded method returns a string, the return value is found here.
  • (property) BgResultInt – If the backgrounded method returns an integer, the return value is found here.
  • (property) BgResultData – If the backgrounded method returns a byte array, the returned data is found here.
  • (method) BgResponseObject – If the backgrounded method returns an HttpResponse object, it may be retrieved by calling this method.


Example

An example of backgrounding the Download method may be found here.

Background Enabling other Chilkat Components
The HTTP component is the first Chilkat component to become background-enabled. The current development plan is to add the identical set of properties and methods to other Chilkat components to background-enable its functionality (such as for POP3, SMTP, IMAP, SSH, SFTP, Zip, MHT, etc.)

Asynchronous HTTP

Notice: The functionality described here is deprecated and replaced by a newer model for asynchronous method calls. The newer model was introduced in Chilkat v9.5.0.52, and is identified by methods having names ending in “Async” which return a task object.

The following example demonstrates the older, deprecated asynchronous HTTP functionality that allows for any HTTP method to be run asynchronously in a background thread:

ASP: HTTP in a Background Thread (Asynchronous HTTP)
SQL Server: HTTP in a Background Thread (Asynchronous HTTP)
C#: HTTP in a Background Thread (Asynchronous HTTP)
C++: HTTP in a Background Thread (Asynchronous HTTP)
MFC: HTTP in a Background Thread (Asynchronous HTTP)
C: HTTP in a Background Thread (Asynchronous HTTP)
Delphi: HTTP in a Background Thread (Asynchronous HTTP)
Visual FoxPro: HTTP in a Background Thread (Asynchronous HTTP)
Java: HTTP in a Background Thread (Asynchronous HTTP)
Perl: HTTP in a Background Thread (Asynchronous HTTP)
PHP: HTTP in a Background Thread (Asynchronous HTTP)
Python: HTTP in a Background Thread (Asynchronous HTTP)
Ruby: HTTP in a Background Thread (Asynchronous HTTP)
VB.NET: HTTP in a Background Thread (Asynchronous HTTP)
Visual Basic: HTTP in a Background Thread (Asynchronous HTTP)
VBScript: HTTP in a Background Thread (Asynchronous HTTP)

Asynchronous Sockets

This blog post is an attempt to explain the concepts of asynchronous socket programming using the Chilkat Socket class/component.   There are five types of socket operations that may occur asynchronously:

  1. Socket read.
  2. Socket write.
  3. Connect to remote hostname:port
  4. Accept connection from client
  5. DNS lookup

A synchronous socket operation is easy to understand.  If you call ReceiveBytes, the method returns only after it has received data on the socket.  If you call Connect, the method returns only after a connection has been established.  If you call AcceptNextConnection, the method returns after an incoming connection has arrived and has been accepted.

Asynchronous methods allow your application to start a socket operation in a background thread.  Your application is then free to do other things while the background thread is working on the socket operation.  For example, your application might do database queries, or update the user interface, etc.  Your application can periodically check to see if the asynchronous operation has completed.  It does this by checking a component property such as AsyncReceivedFinished, AsyncSendFinished, AsyncAcceptFinished, etc.  When the socket operation is finished, your application can get the status via properties such as AsyncReceiveSuccess, AsyncSendSuccess, etc.  Other properties provide the data recieved or the socket object for an accepted connection.

IMPORTANT:  The purpose of the asynchronous socket methods is NOT for queueing up a bunch of socket operations.  For example, if your application calls AsyncReceiveString to initiate a socket receive operation in the background, you cannot call AsyncReceiveString again until the first asynchronous receive completes.   But think about it:  Why would you have more than one asynchronous read oustanding at a time on the same socket?  It doesn’t really make sense.  If Chilkat were to automatically start another read, where would the data go?  When an AsyncReceiveString completes, the received string is available in the AsyncReceivedString property.  Your application can capture or use the received data and initiate the next asynchronous read.  (You may say: “But I want my application to continue reading for performance reasons.”  The answer is:  The operating system is already doing that for you in the background.  The operating system manages connected sockets.  When you receive data on a socket, in most cases you’re simply getting the data that the underlying operating system has already received and has waiting for the application in the underlying socket buffers.)

Regarding asynchronous sending:  Don’t forget that the operating system buffers socket operations.  Unless the outgoing OS buffers are full, or the amount of data you’re sending in a single call is very large, a synchronous send will more-or-less return immediately.  (Did you ever notice when using an FTP program such as WS-FTP, or CuteFTP, that when you upload a file to an FTP server, the upload begins very quickly but then slows down?  It’s because the first amounts of data sent on the socket are buffered by the OS.  The “send” completes while the operating system continues to work (in the background) to send the data in the outgoing socket buffer.  The application is free to continue (in other words, the operating system says “thanks, I have the data and I’ll send it, you may continue with what you’re doing”.)  A socket send operation will only block when the underlying socket send buffers are full.

Back to the main point:  Your application cannot start another asynchronous send operation until the outstanding send completes.  The same goes for Connect and Accept operations.

IMPORTANT:  The Chilkat Socket component is full-duplex, which means:  You may have simultaneous asynchronous receive, send, connect, and accept operations.   You cannot start more than one asynchronous operation of the same type.  For example, if you start an asynchronous receive, you may also start an asynchronous send even though the asynchronous read has not yet completed.