edtFTPnet/PRO - Secure FTP component for .NET | Free Trial | Pricing

How to use asynchronous methods

The regular, synchronous forms of the FTP operations presented through the FTPConnection interface do not return until the operation that they're performing has been completed.  If the connection to the server is slow or if a large file is being transferred then this can result in unacceptable performance, particularly for GUI applications and other applications where FTP operations are performed interactively with a user.  This is why  ExFTPConnection (and SecureFTPConnection) provide advanced asynchronous (or background) functionality.

Most regular methods present in the FTPConnection interface have asynchronous counterparts.  For each synchronous method, there is a corresponding pair of method of the same name, but with Begin and End prefixes. 

For example, the Connect() method corresponds to BeginConnect() and EndConnect().  In the following code, the Print statement is not executed until after the connection to the server has been established.

ftpConnection.Connect();
Print("Connected");

It is common for it to take several seconds to establish a connection so, even this simple task can result in unacceptable GUI performance.

When this is recoded using asynchronous methods, as follows:

ftpConnection.BeginConnect(new AsyncCallback(OnConnect), null;
Print("Connecting");

the BeginConnect() method does not wait for the connection to be established before returning and allowing processing to continue.  Instead, executing immediately returns to the next instruction and the connection is established concurrently on a worker-thread.  It is of course necessary to know when the connection has been established; this is what the AsyncCallback delegate is for.  In this case, this delegate instructs ExFTPConnection to call the method OnConnect() once the connection has been established.  This method is defined as follows:

private void OnConnect(IAsyncResult ar)
{
	Print("Connected");
}

Since the Connect() operation does not return a value, there is no need to call the EndConnect() method.  Some FTP operations do however return values.  In such cases the EndX() method returns the value as illustrated in the following example:

ftpConnection.BeginGetSize(fileName, new AsyncCallback(OnGetSize), ftpConnection);
    .
    .
    .
	private void OnGetSize(IAsyncResult ar)
    {
		SecureFTPConnection c = (SecureFTPConnection)ar.AsyncState;
		long size = c.EndGetSize(ar);
		Print("size = " + size + " bytes");
    }

The asynchronous approach allows the developer to write a highly responsive interface that responds instantly to user actions and provides feedback on how processing is progressing.

Queuing FTP Operations

Unlike other similar implementations, ExFTPConnection allows multiple operations to be queued.  In other words, multiple Begin operations may be invoked without delay.  They will be processed in the order in which they're added.  They will all be executed on the same thread and the callback methods will be invoked between each operation.

Preventing Callbacks and Event-Handlers from Hanging

ExFTPConnection has been designed to make asynchronous processing and event-handling as easy as possible, but occasionally it is necessary to understand how the processing is performed in order to avoid problems that can be difficult to diagnose.

In a Windows Forms application all calls that update the user-interface should be executed on one particular thread.  When this rule is not adhered to .NET 1.1 will exhibit hanging behavior and .NET 2.0 will throw InvalidOperationExceptions.  Microsoft calls such cases "cross-thread calls".

When asynchronous methods are used, ExFTPConnection employs a worker-thread to process FTP operations.  This frees the GUI thread to continue updating the screen and processing user inputs.  However, the decision of which thread the callback should be executed on is not clear-cut.  By default, ExFTPConnection will run asynchronous callbacks and event-handlers on the GUI thread if one is available.  This is generally the most useful since such event-handlers are often used to provide some sort of user-interface-related action.  This behavior can, however, be changed through the UseGuiThreadIfAvailable property.  If this property is set to false then asynchronous callbacks and event-handlers will be executed on the worker-thread.  This is sometimes desirable for performance reasons since it doesn't tie up the GUI thread unnecessarily.