1

我开始创建一些将触发异步操作的类,并且我希望客户端注册一个回调以接收一些结果。最后我达到了以下代码。这只是一个例子,我想知道是否有更好的方法来使用TaskFactoryAction<>, 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      
}

这是客户端类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- await,那么您的代码很接近,但完全正确。问题是回调实际上不会在 UI 线程上执行。为此,您需要使用TaskScheduler.FromCurrentSynchronizationContext().

此外,您的设计在哪里ClientGetClientList()方法对我来说似乎很可疑。这种方法可能属于某种存储库对象,而不是Client.

于 2013-06-03T14:13:27.413 回答