GrapeCity Secure Mail for .NET 4.0J
非同期処理を実装する
すべて展開すべて展開
すべて折りたたむすべて折りたたむ

ここでは、非同期処理を実装する手順について説明します。

旧バージョンとの違い

非同期処理を行う場合、旧バージョン(Mail for .NET 1.0J/Secure Mail 2.0J)では複雑なコード処理が必要でした。たとえば、Imapサーバーへ非同期でログインする場合、同期処理の場合とは異なる専用のメソッド(BeginLoginメソッド)を実行し、さらに非同期ログイン処理の終了時に発生する専用のイベント(EndLoginイベント)に処理を実装する必要があり、その結果メンテナンスしにくいイベント駆動型のコードになっていました。

本バージョンでは、それらのメソッドやイベントに代わり、新たにStartメソッドMarshalメソッドが用意され、シンプルな実装で非同期処理が可能となりました。各メソッドの使用方法について、以下に説明します。

Startメソッド

本製品のメソッドは、同期処理と非同期処理(ブロッキング用途と非ブロッキング用途)の両方をサポートしています。ただし、メソッドを単純に実行した場合、それは同期処理で実行されます。

本バージョンで導入されたStartメソッドは、渡された関数を別のワーカースレッドで実行する機能です。つまり、本製品のメソッドが含まれる関数をStartメソッドに渡すだけで、その関数は呼び出し元のメインスレッドのUIをブロックすることなく、非同期処理で実行されます。このメソッドの構文は単純です。

Smtp1.Start(AddressOf myBlockingFunction, myObject)
        
' ブロッキング処理のメソッドが含まれる関数です。
Private Sub myBlockingFunction(ByVal myObject As Object)
...
End Sub
smtp1.Start(myBlockingFunction, myObject);
        
// ブロッキング処理のメソッドが含まれる関数です。
private void myBlockingFunction(object myObject)
{
  ...
}

このアプローチには、以下のような利点があります。

Marshalメソッド

Startメソッドを使用して呼び出された関数は、別のワーカースレッドで実行されます。そこから呼び出し元のメインスレッド(UIスレッド)へ結果やデータを戻す(マーシャリングする)場合には、その関数内でMarshalメソッドを実行します。

Marshalメソッドを実行すると、メソッドの引数の種類により、メインスレッドでUserStateイベントまたはErrorイベントが発生します。それらのイベントハンドラ内で、Marshalメソッドの引数として渡されたデータを受け取ることができます。

       
' 別のワーカースレッドでMarshalメソッドを実行すると、
' 呼び出し元のメインスレッドでUserStateイベントが発生します。
Smtp1.Marshal("Message from the worker thread!", Nothing)
    
Private Sub Smtp1_UserState(ByVal sender As Object, ByVal e As UserStateEventArgs) Handles smtp1.UserState
  ' Marshalメソッドの引数として渡されたメッセージとオブジェクトを、
  ' メインスレッド側ではUserStateイベントの引数として受け取ることができます。
  MessageBox.Show(e.Message)
End Sub
// 別のワーカースレッドでMarshalメソッドを実行すると、
// 呼び出し元のメインスレッドでUserStateイベントが発生します。
smtp1.Marshal("Message from the worker thread!", null);
    
private void smtp1_UserState(object sender, UserStateEventArgs e)
{
  // Marshalメソッドの引数として渡されたメッセージとオブジェクトを、
  // メインスレッド側ではUserStateイベントの引数として受け取ることができます。
  MessageBox.Show(e.Message);
}
Startメソッドを使用せずに、同期処理として呼び出した関数内でMarshalメソッドが実行されても、動作上特に問題はありません。
StartメソッドとMarshalメソッドの実装例

StartメソッドMarshalメソッドを使用して、非同期処理を実装する場合のコード例を、以下に示します。

Startメソッドを介して実行したsendMail関数は、別のワーカースレッドで非同期で実行されます。関数内で何らかの例外が発生した場合には、Marshalメソッドを実行し、呼び出し元のメインスレッドでErrorイベントを発生させます。Errorイベントのイベントハンドラ内で、Marshalメソッドにより渡されたExceptionの情報を、MessageBoxに表示しています。

       
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
  ' 指定した受信者にメッセージを送信します。
  ' Startメソッドを使用して、操作を(ワーカースレッドで)非同期に実行します。
  ' イベントハンドラはデザイナで追加されました。
  smtp1.Start(AddressOf sendMail, New System.Net.Mail.MailAddress("myRecipient@gmail.com"))
End Sub
    
Private Sub sendMail(ByVal state As Object)
  ' この関数はワーカースレッドで実行され、マルチスレッドの非ブロッキング操作を行います。
  Try
    ' 送信するメソッドを作成します。
    Dim message As New MailMessage()
    Dim recipient As System.Net.Mail.MailAddress = TryCast(state, System.Net.Mail.MailAddress)
    message.To.Add(recipient)
    message.From = "sender@dart.com"
    message.Subject = "Here is your file"
    message.BodyText = "Please see the attached file."
    message.Parts.Add(New Attachment("myAttachment.doc"))
    
    ' セッションパラメーターを設定します。
    smtp1.Session.RemoteEndPoint = New Dart.Mail.IPEndPoint("myMailServer", Smtp.DefaultPort)
    smtp1.Session.Username = "myUsername"
    smtp1.Session.Password = "myPassword"
    smtp1.Session.Authentication = Authentication.Login
    
    ' メッセージを送信してログアウトします。
    smtp1.Send(message)
    smtp1.Close()
  Catch ex As Exception
    ' Errorイベントを発生させ、例外をUIスレッドにマーシャリングします。
    smtp1.Marshal(ex)
  End Try
End Sub
    
Private Sub smtp1_Connection_Log(ByVal sender As Object, ByVal e As DataEventArgs)
  ' 通信ログをテキストボックスに表示します。
  txtLog.AppendText(e.Data.ToString())
End Sub
    
Private Sub smtp1_Error(ByVal sender As Object, ByVal e As ErrorEventArgs)
  ' エラーがあった場合、メッセージを表示します。
  MessageBox.Show(e.GetException().Message, "There was an error while sending the message")
End Sub
private void button1_Click(object sender, EventArgs e)
{
  // 指定した受信者にメッセージを送信します。
  // Startメソッドを使用して、操作を(ワーカースレッドで)非同期に実行します。
  // イベントハンドラはデザイナで追加されました。
  smtp1.Start(sendMail, new System.Net.Mail.MailAddress("myRecipient@gmail.com"));
}
    
private void sendMail(object state)
{
  // この関数はワーカースレッドで実行され、マルチスレッドの非ブロッキング操作を行います。
  try
  {
    // 送信するメッセージを作成します。
    MailMessage message = new MailMessage();
    System.Net.Mail.MailAddress recipient = state as System.Net.Mail.MailAddress;
    message.To.Add(recipient);
    message.From = "sender@dart.com";
    message.Subject = "Here is your file";
    message.BodyText = "Please see the attached file.";
    message.Parts.Add(new Attachment("myAttachment.doc"));
    
    // セッションパラメーターを設定します。
    smtp1.Session.RemoteEndPoint = new Dart.Mail.IPEndPoint("myMailServer", Smtp.DefaultPort);
    smtp1.Session.Username = "myUsername";
    smtp1.Session.Password = "myPassword";
    smtp1.Session.Authentication = Authentication.Login;
    
    // メッセージを送信してログアウトします。
    smtp1.Send(message);
    smtp1.Close();
  }
  catch (Exception ex)
  {
    // Errorイベントを発生させ、例外をUIスレッドにマーシャリングします。
    smtp1.Marshal(ex);
  }
}
    
private void smtp1_Connection_Log(object sender, DataEventArgs e)
{
  // 通信ログをテキストボックスに表示します。
  txtLog.AppendText(e.Data.ToString());
}
    
private void smtp1_Error(object sender, ErrorEventArgs e)
{
  // エラーがあった場合、メッセージを表示します。
  MessageBox.Show(e.GetException().Message, "There was an error while sending the message");
}
上記サンプルコードのsendMail関数は、Startメソッドを使用せずに呼び出すこともできます。この場合は同期処理で実行されます。

 

 


© 2003, GrapeCity inc. All rights reserved.