我是一个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而不必阻止UI有没有办法做这个可能作为TPL或TPL数据流中的事务,因为在我运行它时,POST确实首先启动,但因为get是一个快速操作,它首先完成并返回第一个我希望它们按顺序发生,就像在同步操作中一样......
所以为了改变代码 - 这会是一个更好的方法吗?
foreach (var tuple in taskTuples)
{
factory.StartNew(
() =>
{
this.ProcessSequentially(tuple,client);
}).ContinueWith(this.FinishSequentialTask);
}
答案 0 :(得分: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);
这种简单的方法将在UI线程上同步执行ProcessCallback
。如果您需要使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);
P.S。我离开了Tuple
以最小化代码更改,但我建议您使用自定义类型替换它们;它使代码更加清晰。