如果我将连续组合在一起,它们似乎按照我没想到的顺序执行。
例如:
for (int i = 1; i < 6; i++)
{
HttpRequestMessage request = new HttpRequestMessage();
Task<JsonResult<MyResult>> message = Task.Factory.StartNew<HttpResponseMessage>(() =>
{
Console.WriteLine(i + " started");
return client.SendAsync(request).Result;
})
.ContinueWith<JsonResult<MyResult>>((r) =>
{
var stringresult = r.Result.Content.ReadAsStringAsync().Result;
var deserialized = JsonConvert.DeserializeObject<JsonResult<MyResult>>(stringresult);
Console.WriteLine(deserialized.Id + " deserialized");
return deserialized;
})
.ContinueWith<JsonResult<MyResult>>(m =>
{
Console.WriteLine(m.Id + " completed");
return m.Result;
});
}
现在我希望看到不同的请求交错,我这样做,但我希望看到每个单独的进程按顺序执行:启动,反序列化,完成。但是,有时在反序列化继续之前执行'已完成'继续,如下所示:
1开始了 2开始了 3开始了 4开始了 1反序列化,长度:69
1完成了 5开始了 5反序列化,长度:831
2完成
4反序列化,长度:1022
3完成了 3反序列化,长度:356
4完成了 2反序列化,长度:878
5完成
我在这里缺少什么?
修改
是的,我知道关闭,真正的代码更长,当然处理这个,但我剥离了我认为与问题无关的guff,然后每个人都去关注失踪废话!!它不会改变我所看到的问题或问题。
答案 0 :(得分:0)
正如@Henrik所说,到线程运行时,i
的值将会发生变化。这将使确定线程实际运行的顺序看起来不正确。
尝试将i
传递给函数:
Task<JsonResult<MyResult>> message = Task.Factory.StartNew<HttpRequestMessage>(state => {
Console.WriteLine(state.ToString() + " started");
return client.SendAsync(request).Result;
}, i )
.ContinueWith<JsonResult<MyResult>>((r) =>
{
var stringresult = r.Result.Content.ReadAsStringAsync().Result;
var deserialized = JsonConvert.DeserializeObject<JsonResult<MyResult>>(stringresult);
Console.WriteLine(deserialized.Id + " deserialized");
return deserialized;
})
.ContinueWith<JsonResult<MyResult>>(m =>
{
Console.WriteLine(m.Id + " completed");
return m.Result;
});
答案 1 :(得分:0)
您没有在打印输出中比较相同的ID:s。尝试将最后一个延续更改为
.ContinueWith<JsonResult<MyResult>>(m =>
{
Console.WriteLine(m.Result.Id + " completed");
return m.Result;
});
所以你至少要比较续集中的相同ID。
答案 2 :(得分:0)
因此,您最大的问题是您正在对所有异步操作(SendAsync
和ReadAsStringAsync
)进行同步等待。您只是在后台线程中执行这些同步等待。您的ContinueWith
调用根本没有获得任何价值,因为所有延续都没有异步组件。您也可以将原始代码置于原始StartWith
调用之内;把它放在一个延续中你什么也得不到。
以下是您的程序示例,但没有异步操作的同步等待:
for (int i = 1; i < 6; i++)
{
HttpRequestMessage request = new HttpRequestMessage();
int id = i;
Console.WriteLine("{0} started", id);
var result = client.SendAsync(request)
.ContinueWith(t =>
{
Console.WriteLine("{0} reading", id);
return t.Result.Content.ReadAsStringAsync();
})
.Unwrap()
.ContinueWith(t =>
{
Console.WriteLine("{0} read", id);
var deserialized = JsonConvert.DeserializeObject<JsonResult<MyResult>>(t.Result);
Console.WriteLine("{0} deserialized", id);
return deserialized;
});
}
另请注意,您向我们展示的代码中的一个问题是,您在登录控制台时并未始终使用相同的标识号。我一直使用循环变量,以保持清晰。我还确保获取循环变量的副本,以便我不会关闭循环变量。我还记录了稍微不同的东西,这些东西应该会产生更有趣的结果。