SkyDrive へ移動Framework 4.5 では、Task<TResult> クラスによって非同期処理の結果を取得してあたかも同期処理のような記述を行う事ができるようになりましたが、既存の非同期処理をそのように書き換える為に、TaskCompletionSource<TResult> クラスを使用します。 単純に考えると、Task
を戻り値とするメソッド内は全て管理されていて、その中で登録されたイベントは全て管理下に置かれるようです。イベントが終了するまで、メソッドが終わる事無く、TaskCompletionSource<TResult> クラスの TrySetResult( SetResult との違いは良く解りません )で、値をセットした時にメソッドが終了するように見えます。 こうする事によって、大きなメリットの一つとして、UI スレッドにふつうに戻って来て処理を行えるところであり、当然ループ内の一部として自然に行を追加しながら非同期を実現する事ができました MainWindow.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Net; using System.Windows; using System.Windows.Input; using System.Collections.ObjectModel; using TKMP.Net; using System.IO; using TKMP.Reader; using System.Threading; using System.Threading.Tasks; namespace WPF_DataGrid_MailGet1 { public partial class MainWindow : Window { private MainViewModel mvm = new MainViewModel(); private ImapClient client = null; // ********************************************* // コンストラクタ // ********************************************* public MainWindow() { InitializeComponent(); this.dataGrid1.DataContext = mvm; } // 接続および、メールヘッダの取得 private async void actButton_Click(object sender, RoutedEventArgs e) { mvm.mail_data.Clear(); BasicImapLogon logon = new BasicImapLogon(this.userName.Text, this.password.Password); client = new ImapClient(logon, "imap.gmail.com", 993); client.AuthenticationProtocol = AuthenticationProtocols.SSL; if (!client.Connect()) { return; } // メールデータ一覧を格納するオブジェクト IMailData[] md = client.GetMailList(); // データがありません if (md == null) { return; } // メールデータの数 mailCount.Text = md.Length.ToString(); // 読込み制限 int maxCount = 20; int idx = 0; // 非同期で全て表示 foreach (var data in md) { idx++; if (idx > maxCount) { break; } // Framework 4.5 : 値を返す非同期処理 MailReader reader = await ReadBodyAnsync( data ); // UI スレッドに戻って来ているので、特殊な処理は必要無い string from = ""; string subject = ""; string mdate = ""; // ヘッダの一覧より、目的のヘッダを探す foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection) { if (headerdata.Name == "From") { from = headerdata.Data; } if (headerdata.Name == "Subject") { subject = headerdata.Data; } if (headerdata.Name == "Date") { mdate = headerdata.Data; } } // 行追加 mvm.mail_data.Add(new ItemViewModel() { from = from, subject = subject, mdate = mdate }); } // ソース的には、順次処理なので全てのデータ処理後のクローズ client.Close(); } // ********************************************* // 戻り値を返す事のできる非同期処理 【開始】 // ********************************************* private TaskCompletionSource<MailReader> tcs = null; private Task<MailReader> ReadBodyAnsync(IMailData MailData) { // 戻り値用のクラス tcs = new TaskCompletionSource<MailReader>(); // 個別にイベント登録 MailData.BodyLoaded += new EventHandler(MailData_event); // 非同期処理開始 MailData.ReadBodyAnsync(); return tcs.Task; } // 本来のイベント処理 private void MailData_event(object sender, EventArgs e) { IMailData MailData = (IMailData)sender; // イベント削除 MailData.BodyLoaded -= new EventHandler(MailData_event); // 本文無し( 本文が必要な場合は、false で、reader.MainText ) MailReader reader = new MailReader(MailData.DataStream, true); // **************************** // 戻り値用のクラスの戻り値をセット // **************************** tcs.TrySetResult(reader); } // ********************************************* // 戻り値を返す事のできる非同期処理 【終了】 // ********************************************* // ダブルクリック private void dataGrid1_MouseDoubleClick(object sender, MouseButtonEventArgs e) { Debug.WriteLine(dataGrid1.SelectedIndex); } } }
参考ページ c# - Best way to convert callback-based async method to awaitable task - Stack Overflow c# - TaskCompletionSource : When to use SetResult() versus TrySetResult(), etc - Stack Overflow 関連するページ ▼ このページの処理の元となった、通常のイベント非同期処理 WPF(C#) : 『DataGrid に、TKMP.DLL を使用して非同期にメールヘッダを受信する』 テンプレート
|
【VS(C#)の最新記事】
- Replit : cs-list
- C# : Excel の新しいブックのデフォルトのシートのセルに直接値をセットして、オートフィルを Range オブジェクトから実行する
- C#( Form ) : ウインドウ枠の無い吹き出しの作成
- C# のタプル( Visual Studio 2017 でテスト )
- C# : インターネット上の JSON ファイルのフォーマットを クラスとして定義して1行でオブジェクト化して使用する
- C# の文法的文字列処理
- C# : System.Data.Odbc によるデータベースのテーブルからのデータ取得処理( サンプルの SQL は MySQL 用です )
- C# : Excel を データベースとして DataGridView に読み込む
- C# : dynamic 型 による Excel へのアクセス
- C# : フォームを表示せずに、通知領域にアイコンを表示させる常駐プログラム
- Microsoft Access に対してSQLを入力してその結果を DataGridView に表示する最も簡単なコード
- C# : System.Data.Odbc データ取得(SELECT)処理( MySQL ) : ※ using 無し( Dispose 実行 )
- C# : SQL 文を外部テキストにして、String.Format でデータ部分を置き換えて利用する
- C# コンソールアプリを AN HTTPD で実行
- C# : SQLServer( SQLExpress ) の SMO を使用してテーブルの CREATE TABLE 文 を取得する
- C# : DataGridView に TKMP.DLL の IMAP(POP3) で受信したメールを非同期に表示する( 添付ファイルも取得 )
- C# : TKMP.DLLを使った、メール送信テンプレート
- C# と VB.net : TKMP.DLL を使って IMAP でメール本文の一覧を取得する( コンソール )
- C# でDataTable と DataSource を使用して、DataGridView にデータを表示するテンプレート( 行をダブルクリックしてダイアログを表示して行データを処理 )
- (C#) / VS2010 または VS2012 : TKMP.DLL(3.1.2 または 3.1.8)を使った、『さくらインターネット』用メール送信テンプレート