4

カスタムコントロールがあり、このコントロールがユーザーに公開するインターフェイスがあります。

public interface ILookupDataProvider
{
    string IdColumnName { get; }

    IEnumerable<IDataColumn> Metadata { get; set; }

    void GetDataAsync(string parameters, 
        Action<IEnumerable<object>> onSuccess, Action<Exception> onError);
}

だから、それは非同期操作を公開する私の試みですGetDataAsync

しかし、インターフェイスを実装するクラスにこのメソッドを実装する方法がわかりません。実行してonCompletionからデリゲートが呼び出されるメソッドがあるので、この部分を理解しています。onSucessonError

誰かがそれらを書く方法の構文を手伝ってもらえますか?

編集:

4.0で、awaitコマンドを使用できません

編集2:

DevForceフレームワークを使用してデータをロードしますが、このサンプルのために、たとえばWCFサービスを実行してみましょう。インターフェイスの実装でWCFサービス呼び出しをどのようにラップしますか?

また、非同期操作を提示するためにこのようなインターフェースを作成しても大丈夫だと思いますか?たとえば、イベントでそれを別の方法で行いますか?

4

3 に答える 3

6

ここでの基本的な考え方は、クエリがバックグラウンド スレッドで発生するということです。操作が完了したら、onSuccessおよびonErrorコールバックを使用して、新しい値を報告します。例えば

void GetDataAsync(
  string parameters, 
  Action<IEnumerable<object>> onSuccess, 
  Action<Exception> onError) {

  WaitCallback doWork = delegate { 
    try { 
      IEnumerable<object> enumerable = GetTheData(parameters);
      onSuccess(enumerable);
    } catch (Exception ex) {
      onError(ex);
    }
  };

  ThreadPool.QueueUserWorkItem(doWork, null);
}
于 2011-11-07T21:07:26.470 に答える
3

あなたは本当にこのパターンを使いたくない:

void GetDataAsync(string parameters, 
    Action<IEnumerable<object>> onSuccess, Action<Exception> onError);

代わりに、これを使用します。

Task GetDataAsync(string parameters);

を返すTask場合、非同期の作業単位を表すインスタンスを返します。そこから、API のコンシューマーは呼び出しを選択しContinueWith、成功した場合、またはエラーが発生した場合に何をするかを決定できます。

ただし、あなたの例には設計上の欠陥があります。という名前のメソッドではGetDataAsync、データが返されることを期待しています。それは問題ではありません。署名を次のように変更できます。

Task<MyData> GetDataAsync(string parameters);

これにより、 のプロパティTask<T>を使用して結果を取得できる が返されるようになりました (タスクが完了していない場合はブロックされます)。または、非同期操作が完了したときにメソッドを再度使用してデータを処理できます。ResultContinueWith

さらに、パラメーターのCancellationToken構造体インスタンスを取得して、操作をキャンセルする必要があるかどうかを判断できます。

Task<MyData> GetDataAsync(string parameters, 
    CancellationToken cancellationToken);

ここでも、ContinueWithキャンセル時に実行するアクションを示すことができます。

これは、 Async CTP を使用するメソッドawaitAsync CTPを使用するメソッドが現在モデル化されている方法であることに注意してください。彼らは戻ってきているか; コードで同じことを行うと、これらの言語機能が組み込まれたときに準備が整います。asyncTaskTask<T>

于 2011-11-07T21:14:48.793 に答える
1

タスクを使用するには、このように使用できます。覚えておくべき唯一のトリッキーなことは、TaskScheduler.FromCurrentSynchronizationContext() で達成される UI スレッドでコールバックを実行することです。これにより、何か問題が発生した場合に UI を更新したり、メッセージボックスを表示したりできます。

このようなイベント ドリブンの性質により、WCF 呼び出しを開始するボタンを叩くと、要求を送信した順序で結果が返されない場合があります。新しい操作を開始する場合は、開始されたタスクを保存し、最後に開始されたタスクをキャンセルすることでこれを防ぐことができます。または、タスクの実行中に後続の要求を単に無視することもできます。

private void button1_Click(object sender, EventArgs e)
{
    GetDataAsync("www.data.com").ContinueWith(result =>
        {
            if (result.Exception != null)
            {
                MessageBox.Show(this, "Error: {0}" + result.Exception, "Error");
            }
            else
            {
                foreach (var obj in result.Result)
                {
                    textBox1.Text += obj.ToString();
                }
            }
        },
        TaskScheduler.FromCurrentSynchronizationContext()
        );

}

Task<IEnumerable<object>> GetDataAsync(string parameters)
{
    return Task<IEnumerable<object>>.Factory.StartNew(() =>
    {
        Thread.Sleep(500);
      //  throw new ArgumentException("uups");
        // make wcf call here
        return new object[] { "First", "second" };
    });
}
于 2011-11-07T21:43:02.183 に答える