为什么在继续使用其他内容时取消原始任务?

Hao*_*wei 3 .net c# task task-parallel-library

我进入C#编程已经有4周了.这真的很有趣,然而,我痛苦的屁股:

当我HttpClient.PostAsync()独自开始一个任务时,它工作正常.但如果我继续其他事情,原始任务将被取消,而不是我.看起来这个任务不乐意继续.

Task<HttpResponseMessage> task0;
Task task1;

using (var client = new HttpClient())
{
    HttpContent content = new ByteArrayContent(new byte[]{});

    task0 = client.PostAsync("<valid http address>", content);

    task1 = task0.ContinueWith((t) =>
    {
         // Do nothing
    });
}

task1.Wait();

// I got task0.IsCanceled == true here
Run Code Online (Sandbox Code Playgroud)

我试过了:

1,task0.wait()马上添加后PostAsync()会解决问题,但这不是我想要的.因为我需要异步的性能优势,并且这样做会使它完全同步.

2,添加task0.wait()之前task1.wait()会导致一个TaskCanceledExcpetion.

3,删除task1并等待就task0可以了.

4,调用task0.start()将得到"开始可能不会被调用承诺式任务".

所以,有人告诉我,我做错了什么?

PS:

在我问这个问题之前,我用Google搜索了好几天.StackOverflow的一些问题看起来可能相关,但事实证明它们与我的不一样.

谁取消了我的任务?她/他在问为什么继续任务没有执行.

为什么会发生TaskCanceledException?她/他搞乱了我从未做过的CancellationToken,并得到了意想不到的结果.

我也读过这个任务取消,但仍然没有任何线索.

Yur*_*ura 7

完成HttpClient之前你最有可能得到的处理PostAsync.删除using语句用于测试目的,一切都将按预期工作.当请求完成时,您应该将您的客户端部署在不同的位置.

此外,HttpClient 如果您的应用程序逻辑允许,许多人会建议尽可能多地重用单个实例.


Pau*_*ner 5

所以,这个代码似乎是在HttpClient你连接延续时立即处理,这很可能不是你想要的.

如果要使用using语句来处置客户端实例,则需要使用asyncawait关键字.以下代码等同于您的示例,编译器为您提供了延续.

public async Task FooAsync()
{
    using (var client = new HttpClient())
    {
        HttpContent content = new ByteArrayContent(new byte[]{});

        await client.PostAsync("<valid http address>", content);

        // Continue your code here.
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要继续使用在没有编译器帮助的情况下创建的continuation,可以将处理逻辑放在一个延续中:

Task<HttpResponseMessage> task0;
Task task1;

var client = new HttpClient();

HttpContent content = new ByteArrayContent(new byte[]{});

task0 = client.PostAsync("<valid http address>", content);

task1 = task0.ContinueWith((t) =>
{
    client.Dispose();
})

task1.Wait();
Run Code Online (Sandbox Code Playgroud)