0

我是一个 TPL 新手。不确定这个库是否是要走的路,但我想按顺序运行一组异步任务,但不阻塞 UI,而是按顺序运行并按启动顺序回调 - 有点像运行它们同步。因此,只有在任务完成并有 HttpResponseMessage 时才会有效地回调。然后才开始下一个任务。

所以行为将是

运行长时间运行的任务 1,当它完成回调时,我们可以对 UI 做一些事情,然后运行下一个长时间运行的任务,当它完成回调时,我们可以更新 UI。运行一个较短的任务,当它完成回调以便我们可以更新 UI

我已经看到了一些使用调度程序的示例,但无论如何这是我的代码

private void RunSequentially()
{
        var lcts = new LimitedConcurrencyLevelTaskScheduler(1);
        var factory = new TaskFactory(lcts);
        string username = "user";
        string password = "password";
        var handler = new HttpClientHandler
            {
               Credentials = new NetworkCredential(username, password), PreAuthenticate = true 
            };
        var client = new HttpClient(handler);

        List<Tuple<string,string,string>> taskTuples = new List<Tuple<string, string, string>>();
        taskTuples.Add(new Tuple<string, string, string>("POST", "http://longrunning", XDocument.Load(@"./somefile.xml").ToString()));
        taskTuples.Add(new Tuple<string, string, string>("GET", "http://getItem", null));

        factory.StartNew(
            () =>
                {
                    foreach(var tuple in taskTuples)
                    {
                        ProcessSequentially(tuple,ProcessCallback, client);
                    }
                });
    }

和 ProcessSequentially 方法

private async void ProcessSequentially(Tuple<string, string, string> tuple, Action<string> callback, HttpClient client)
    {
        HttpResponseMessage message = null;
        if (tuple.Item1 == "POST")
        {
            message = await
                client.PostAsync(
                    tuple.Item2,
                    new StringContent(tuple.Item3));
        }
        else
        {
            message = await
                client.GetAsync(
                    tuple.Item2);
        }

        callback(message.ReasonPhrase);


    }

现在假设 post 任务将是长时间运行的任务 - 我需要先启动长时间运行的任务并首先回调,然后在第一个回调后启动短时间运行的 GET,而不必通过 WaitAll 阻塞 UI等有没有办法做到这一点,也许作为 TPL 或 TPL 数据流中的一个事务,因为在我运行这个的那一刻,POST 确实首先开始,但是因为 get 是一个快速操作,它首先完成并首先返回,我想它们像同步操作一样按顺序发生...

因此,为了更改代码 - 这会是更好的方法吗?

foreach (var tuple in taskTuples)
        {
            factory.StartNew(
            () =>
            {
                this.ProcessSequentially(tuple,client);
            }).ContinueWith(this.FinishSequentialTask);
        }
4

1 回答 1

1

您需要顺序异步代码。await非常适合这个:

private async Task RunSequentially()
{
  string username = "user";
  string password = "password";
  var handler = new HttpClientHandler
  {
    Credentials = new NetworkCredential(username, password), PreAuthenticate = true 
  };
  var client = new HttpClient(handler);

  List<Tuple<string,string,string>> taskTuples = new List<Tuple<string, string, string>>();
  taskTuples.Add(new Tuple<string, string, string>("POST", "http://longrunning", XDocument.Load(@"./somefile.xml").ToString()));
  taskTuples.Add(new Tuple<string, string, string>("GET", "http://getItem", null));
  foreach (var tuple in taskTuples)
  {
    await Process(tuple, ProcessCallback, client);
  }
}

private async Task Process(Tuple<string, string, string> tuple, Action<string> callback, HttpClient client)
{
  HttpResponseMessage message = null;
  if (tuple.Item1 == "POST")
  {
    message = await
        client.PostAsync(
            tuple.Item2,
            new StringContent(tuple.Item3));
  }
  else
  {
    message = await
        client.GetAsync(
            tuple.Item2);
  }

  callback(message.ReasonPhrase);
}

private void ProcessCallback(string reason);

这种简单的方法将ProcessCallback在 UI 线程上同步执行。如果你需要做ProcessCallback异步,你可以这样做:

private async Task Process(Tuple<string, string, string> tuple, Func<string, Task> callback, HttpClient client)
{
  HttpResponseMessage message = null;
  if (tuple.Item1 == "POST")
  {
    message = await
        client.PostAsync(
            tuple.Item2,
            new StringContent(tuple.Item3));
  }
  else
  {
    message = await
        client.GetAsync(
            tuple.Item2);
  }

  await callback(message.ReasonPhrase);
}

private async Task ProcessCallback(string reason);

PS 我留下了你Tuple的 s 以尽量减少代码更改,但我建议你用自定义类型替换它们;它使代码更清晰。

于 2012-11-08T14:59:35.203 回答