使用任务工厂和回调创建异步方法

时间:2013-06-03 10:43:03

标签: c# asynchronous taskfactory

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

这是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的{​​{1}} / async个版本。 这种方法是否正确?:

webrequest

2 个答案:

答案 0 :(得分:5)

首先,你的方法似乎并不是异步的,所以你不会从使它看起来像一个人那里获得太多收益。如果您的方法的用户决定在另一个线程上运行它,他们可以自己完成。

其次,如果您可以使用C#5.0,则应遵循the Task-based asynchronous pattern,以使您的方法更易于使用。有了这个(假设你有理由忽略我上面的第一点),你的代码可能如下所示:

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()

此外,Client采用GetClientList()方法的设计对我来说似乎很可疑。这种方法可能属于某种存储库对象,而不属于Client

答案 1 :(得分:-2)

但是如果你使用await client.GetClientAsync .... theard将被阻止。

添加回调的任何新方法?或者我应该使用4.0 TPL?

我没有看到等待的价值。它阻止了当前线程,丢失了其他任务。