More .NET components

Asynchronous operations

Sample codes in this section uses Pop3 class. Same principles applies to Smtp, Imap and Ews classes as well.

Task-based Asynchronous Pattern (.NET 4.0 or later) #

.NET 4.0 introduced the Task-based Asynchronous Pattern (TAP). Rebex Secure Mail supports it as well - just reference the assemblies for .NET 4.0 from your project.

CSharp

// create POP3 client instance, connect, log in
// (same applies for Rebex.Net.Smtp/Imap/Ews)
// ...

// start async operation
Task<Pop3MessageCollection> t = pop3.GetMessageListAsync(Pop3ListFields.FullHeaders);

// set continuation method
t.ContinueWith(GetMessageListFinished);

VisualBasic

' create POP3 client instance, connect, log in
' (same applies for Rebex.Net.Smtp/Imap/Ews)
' ...

' start async operation
Dim t As Task(Of Pop3MessageCollection) = pop3.GetMessageListAsync(Pop3ListFields.FullHeaders)

' set continuation method
t.ContinueWith(AddressOf GetMessageListFinished)

Sample asynchronous continuation method:

CSharp

// this method is called when the async operation is completed
private void GetMessageListFinished(Task<Pop3MessageCollection> t)
{
    // show error if any
    if (t.IsFaulted)
    {
        Console.WriteLine("An error occurred: {0}", t.Exception.ToString());
        return;
    }

    // show cancel notification
    if (t.IsCanceled)
    {
        Console.WriteLine("Operation was canceled.");
        return;
    }

    // get operation result
    Pop3MessageCollection list = t.Result;

    // show result
    Console.WriteLine("Listed {0} item(s).", list.Count);
}

VisualBasic

' this method is called when the async operation is completed
Private Sub GetMessageListFinished(t As Task(Of Pop3MessageCollection))
    ' show error if any
    If t.IsFaulted Then
        Console.WriteLine("An error occurred: {0}", t.Exception.ToString())
        Return
    End If

    ' show cancel notification
    If t.IsCanceled Then
        Console.WriteLine("Operation was canceled.")
        Return
    End If

    ' get operation result
    Dim list As Pop3MessageCollection = t.Result

    ' show result
    Console.WriteLine("Listed {0} item(s).", list.Count)
End Sub

'await' operator support (.NET 4.5 or later) #

.NET 4.5 introduced the 'await' operator, which makes writing asynchronous code more easy than ever before. Rebex Secure Mail supports it as well, just reference the assemblies for .NET 4.0 from your project.

CSharp

// same applies for Rebex.Net.Smtp/Imap/Pop3/Ews
private async void GetList()
{
    try
    {
        // get list asynchronously
        Pop3MessageCollection list = await pop3.GetMessageListAsync(Pop3ListFields.FullHeaders);

        // show result
        Console.WriteLine("Listed {0} item(s).", list.Count);
    }
    catch (Pop3Exception ex)
    {
        if (ex.Status == Pop3ExceptionStatus.OperationAborted)
            Console.WriteLine("Operation was canceled.");
        else
            Console.WriteLine("An error occurred: {0}.", ex.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("An error occurred: {0}", ex.ToString());
    }
}

VisualBasic

' same applies for Rebex.Net.Smtp/Imap/Pop3/Ews
Private Async Sub GetList()
    Try
        ' get list asynchronously
        Dim list As Pop3MessageCollection = Await pop3.GetMessageListAsync(Pop3ListFields.FullHeaders)

        ' show result
        Console.WriteLine("Listed {0} item(s).", list.Count)
    Catch ex As Pop3Exception
        If ex.Status = Pop3ExceptionStatus.OperationAborted Then
            Console.WriteLine("Operation was canceled.")
        Else
            Console.WriteLine("An error occurred: {0}.", ex.Message)
        End If
    Catch ex As Exception
        Console.WriteLine("An error occurred: {0}", ex.ToString())
    End Try
End Sub

IAsyncResult pattern (Begin/End methods) #

The Asynchronous Programming Model (APM) pattern, also known as IAsyncResult (or Begin/End) pattern, was introduced in .NET 1.0. When you reference Rebex assemblies for .NET 2.0 in your project, this is the pattern you can use.

CSharp

// start async operation, specify callback
IAsyncResult ar = pop3.BeginGetMessageList(Pop3ListFields.FullHeaders, GetMessageListFinished, null);

VisualBasic

' start async operation, specify callback
Dim ar = pop3.BeginGetMessageList(Pop3ListFields.FullHeaders, AddressOf GetMessageListFinished, Nothing)

Sample asynchronous callback method:

CSharp

// this method is called when the Begin method is completed
private void GetMessageListFinished(IAsyncResult ar)
{
    try
    {
        // get operation result
        Pop3MessageCollection list = pop3.EndGetMessageList(ar);

        // show result
        Console.WriteLine("Listed {0} item(s).", list.Count);
    }
    catch (Pop3Exception ex)
    {
        if (ex.Status == Pop3ExceptionStatus.OperationAborted)
            Console.WriteLine("Operation was canceled.");
        else
            Console.WriteLine("An error occurred: {0}.", ex.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("An error occurred: {0}", ex.ToString());
    }
}

VisualBasic

' this method is called when the Begin method is completed
Sub GetMessageListFinished(ByVal ar As IAsyncResult)
    Try
        ' get operation result
        Dim list As Pop3MessageCollection = pop3.EndGetMessageList(ar)

        ' show result
        Console.WriteLine("Listed {0} item(s).", list.Count)
    Catch ex As Pop3Exception
        If ex.Status = Pop3ExceptionStatus.OperationAborted Then
            Console.WriteLine("Operation was canceled.")
        Else
            Console.WriteLine("An error occurred: {0}.", ex.Message)
        End If
    Catch ex As Exception
        Console.WriteLine("An error occurred: {0}", ex.ToString())
    End Try
End Sub

Using IAsyncResult in .NET 4.0 or later #

If you reference Rebex assemblies for .NET 4.0 or later from your project, but still wish to use the old-style IAsyncResult asynchronous pattern, include the Rebex.Legacy namespace.

By default, .NET 4.0 assemblies only present a Task-based pattern (TAP) asynchronous API. Rebex.Legacy namespace defines all the Begin/End methods as extension methods, making it possible to use to easily port old code to .NET 4.0 or higher.

CSharp

using Rebex.Legacy;

VisualBasic

Imports Rebex.Legacy

SynchronizationContext support for events #

When an asynchronous method on the Smtp, Imap or Pop3 object raises an event, it's dispatched using the synchronization context captured when the operation was started.

This greatly simplifies writing GUI applications (Windows Forms and WPF) because all the events are raised on the applications GUI thread, eliminating the need to explicitly marshal the calls using the Invoke method.

If you need to disable this functionality, set Smtp.Settings.RaiseEventsFromCurrentThread to true. This will cause all the events to be raised on the background operation's thread. (The same applies to Imap and Pop3.)