GrapeCity Secure Mail for .NET 4.0J > 基本的な使用方法 > コンポーネントの使用手順 > 非同期処理を実装する |
ここでは、非同期処理を実装する手順について説明します。
非同期処理を行う場合、旧バージョン(Mail for .NET 1.0J/Secure Mail 2.0J)では複雑なコード処理が必要でした。たとえば、Imapサーバーへ非同期でログインする場合、同期処理の場合とは異なる専用のメソッド(BeginLoginメソッド)を実行し、さらに非同期ログイン処理の終了時に発生する専用のイベント(EndLoginイベント)に処理を実装する必要があり、その結果メンテナンスしにくいイベント駆動型のコードになっていました。
本バージョンでは、それらのメソッドやイベントに代わり、新たにStartメソッドやMarshalメソッドが用意され、シンプルな実装で非同期処理が可能となりました。各メソッドの使用方法について、以下に説明します。
本製品のメソッドは、同期処理と非同期処理(ブロッキング用途と非ブロッキング用途)の両方をサポートしています。ただし、メソッドを単純に実行した場合、それは同期処理で実行されます。
本バージョンで導入された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) { ... }
このアプローチには、以下のような利点があります。
同期処理と非同期処理とで、一つの関数を共用できます。関数を別個に作成する必要はありません。Startメソッドを使用すれば非同期で、Startメソッドを使用しなければ同期処理で、呼び出した関数が実行されます。
関数内のメソッドは直列に呼び出されるので、コードのメンテナンスが容易です。多数のイベントハンドラを実装し、あるハンドラから別のハンドラにジャンプするようなコードを記述する必要はありません。
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メソッドを介して実行した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メソッドを使用せずに呼び出すこともできます。この場合は同期処理で実行されます。 |