1

非同期操作を起動するいくつかのクラスの作成を開始しており、クライアントがコールバックを登録して結果を受け取るようにしたいと考えています。最終的に以下のコードにたどり着きました。TaskFactoryあくまで一例ですので、他にもっと良い方法があれば教えていただきたいです。Action<>, Func<>

クライアントの基本的な例を次に示します。

Client client2 = new Client();
client2.GetClientList(ClientCallBack);


private static void ClientCallBack(List<Client> listado)
{ 
  //Receive the list result and do some stuff in UI      
}

Client クラスのGetCLientList非同期の例を次に示します。

public void GetClientList(Action<List<Client>> Callback)
{
  List<Client> listado=null;

  Task.Factory.StartNew(() =>
    {
      listado = new List<Client>{
        new Client{ apellidos="Landeras",nombre="Carlos",edad=25},
        new Client{ apellidos="Lopez", nombre="Pepe", edad=22},
        new Client{ apellidos="Estevez", nombre="Alberto", edad=28}
      };

    //Thread.Sleep to simulate some load
    System.Threading.Thread.Sleep(4000);
  }).ContinueWith((prevTask) =>
    {
      Callback(listado);
    }
  );
}

それを行うより良い方法はありますか?Task関数から戻っcontinueWithてクライアント側に登録できることはわかっていますが、クラス内にラップしたいと考えています。

編集

別の例を投稿しています。sync/asyncのバージョンを作成しようとしていましたwebrequest。このアプローチは正しいですか?:

public string ExecuteRequest(string url)
{
  HttpWebRequest httpwebrequest = (HttpWebRequest) WebRequest.Create(url);
  HttpWebResponse httpwebresponse = (HttpWebResponse) httpwebrequest.GetResponse();

  using (StreamReader sr = new StreamReader(httpwebresponse.GetResponseStream()))
  {
    return sr.ReadToEnd();
  }
}

public void ExecuteRequestAsync(string uri,Action<string> callbackResult)
{
  Task.Factory.StartNew(() => ExecuteRequest(uri), CancellationToken.None)
    .ContinueWith((task) => callbackResult(task.Result));           
}
4

1 に答える 1

5

まず、あなたのメソッドは実際には非同期ではないようです。メソッドのユーザーが別のスレッドで実行することにした場合は、自分で実行できます。

次に、C# 5.0 を使用できる場合は、メソッドを使いやすくするために、タスク ベースの非同期パターンに従う必要があります。これで (そして、上記の最初のポイントを無視する理由があると仮定すると)、コードは次のようになります。

public Task<List<Client>> GetClientListAsync()
{
    return Task.Run(() =>
    {
        var list = new List<Client>
        {
            new Client { apellidos="Landeras", nombre="Carlos", edad=25 },
            new Client { apellidos="Lopez", nombre="Pepe", edad=22 },
            new Client { apellidos="Estevez", nombre="Alberto", edad=28 }
        };

        //Thread.Sleep to simulate some load
        System.Threading.Thread.Sleep(4000);

        return list;
    });
}

または、コードを実際に非同期にしたい場合:

public async Task<List<Client>> GetClientListAsync()
{
    var list = new List<Client>
    {
        new Client { apellidos="Landeras", nombre="Carlos", edad=25 },
        new Client { apellidos="Lopez", nombre="Pepe", edad=22 },
        new Client { apellidos="Estevez", nombre="Alberto", edad=28 }
    };

    //Task.Delay() to simulate some load
    await Task.Delay(4000);

    return list;
}

どちらの場合も、次のasyncようなメソッドからのコールバックを使用せずに、このメソッドを使用できます。

var client = new Client();
var list = await client.GetClientListAsync();
//Receive the list result and do some stuff in UI

async第 3 に、 -を使用したくない (または使用できなかった) 場合await、コードは近いですが、非常に適切です。問題は、コールバックが実際には UI スレッドで実行されないことです。そのためには、 を使用する必要がありますTaskScheduler.FromCurrentSynchronizationContext()

Clientまた、メソッドを持つあなたのデザインは、GetClientList()私には疑わしいようです。このようなメソッドは、おそらく ではなく、ある種のリポジトリ オブジェクトに属していますClient

于 2013-06-03T14:13:27.413 に答える