2011-11-07 13 views
4

私はカスタムコントロールを持っていて、このコントロールがユーザーに公開するインターフェイスを持っています。非同期操作の頭を包み込む必要があります

public interface ILookupDataProvider 
{ 
    string IdColumnName { get; } 

    IEnumerable<IDataColumn> Metadata { get; set; } 

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

だから、それはGetDataAsync

で非同期操作を公開する私の試みだが、私は、インターフェイスを実装して、私のクラスでこのメソッドを実装する方法がわかりません。私は実行するメソッドがあるので、この部分を理解してからonCompletiononSucessまたはonError代理人が呼び出されます。

誰かがそれらを書く方法に関する構文を助けることができますか?

EDIT:

それは4.0だと私は

EDIT 2 awaitコマンドを使用することはできません:私は、データをロードするために效率フレームワークを使用しますが、このサンプルのため

- さんは、WCFをやらせます例えばサービス。インターフェイスの実装でWCFサービスコールをどのようにラップしますか?

また、このようなインターフェイスを作成して非同期操作を行うこともOKだと思いますか?あなたはイベントなどと違ってやりますか?

+0

async/awaitの使用後、または正確に何を知りたいですか? – flq

+0

.NET 3.5または.NET 4をターゲットにしていますか –

+0

VS2010を使用しているため、非同期待機を使用できません。このインターフェイスの実装を書きたいので構文を理解できません。非シンプルな非同期実装でも、アクションのコード化方法を理解するのに役立ちます。 – katit

答えて

6

ここでの基本的な考え方は、クエリがバックグラウンドスレッドで発生するということです。操作が完了したら、新しい値を報告するためにonSuccessonErrorコールバックを使用します。 、あなたが戻ってきているTaskを返すには

Task GetDataAsync(string parameters); 

void GetDataAsync(string parameters, 
    Action<IEnumerable<object>> onSuccess, Action<Exception> 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); 
} 
+1

'Task'または' Task 'が使用されていない理由が分からない場合、これらのクラスの全ポイントは、メソッドのロジック外で非同期操作の完了の通知の制御をプッシュすることです。 – casperOne

3

のためにあなたは本当にこのパターンを使用したくありません非同期作業単位を表すインスタンスそこから、APIの消費者はContinueWithに電話して、成功したときに何をするか、エラーがあるかどうかを決めることができます。

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

Task<MyData> GetDataAsync(string parameters); 

この今あなたが(タスクが実行されていない場合、それはブロックされます)結果を得るためのResult propertyを使用することができますTask<T>を返しますか、非同期操作が完了したら、ContinueWithメソッドを再度使用してデータを処理できます。

また、あなたがあなたの操作をキャンセルする必要があるかどうかを決定するためのパラメータのCancellationToken structureインスタンスを実行できます。

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

ここでも、ContinueWithあなたがキャンセルに取るべきアクションを指示することができます。

これはとasyncを使用してAsync CTPのメソッドが現在どのようにモデル化されているのかを示しています。彼らはTaskまたはTask<T>を返す。あなたのコードで同じことをすると、これらの言語機能が焼き付けられたときに準備が整います。

+0

私はあなたが正しいと感じていますが、あなたの例は私の頭を掴むのがさらに複雑です:)私はまだ静かでなければならないことを知っています。あなたが私にインターフェイスを実装しているクラスに実装する方法を教えてくれないか、WCF呼び出しをこれにラップするなどしない限り、私はそれを使うことはできないと思います。キャンセルして操作を続けても構いません。例外やデータで終了したときを知る必要があります – katit

+0

@katit、http://msdn.microsoft.com/en-us/library/dd537610%28v=VS.100%29.aspx – ebb

+0

これはSilverlightで利用できますか?私はタスクが利用できないと思う。 – katit

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" }; 
    }); 
} 
+0

残念ながら私はSilverlight 4でタスクを使用できない – katit

関連する問題