如果任务等待的东西,任务状态更改为 RanToCompletion [英] Task status changes to RanToCompletion if the Task await's something

查看:25
本文介绍了如果任务等待的东西,任务状态更改为 RanToCompletion的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该问题描述了此处发现的相同问题 - MSDN 开发者论坛.该问题没有公认的答案,给出的任何答案都不能应用于我的案例(因此是一个不同的问题).

The question describes the same problem found here - MSDN Developer Forum. The question does not have an accepted answer, neither any of the answers given can be applied to my case (hence a different question).

问题也源自我之前问过的问题,但是,由于不同的性质和更具体的问题,我在问一个新的.

Question is also derived from one I asked previously, but, due to different nature and more specific problem, I'm asking a new one.

完整代码可以在这里找到:http://pastebin.com/uhBGWC5e
* 唯一改变的是任务完成检查(while -> Task.WhenAll).

Full code can be found here: http://pastebin.com/uhBGWC5e
* Only thing changed is the task completion check (while -> Task.WhenAll).

在任务内部等待异步操作时,任务状态更改为 RanToCompletion,即使任务仍在运行.

When awaiting an async operation inside of a Task, the Task status changes to RanToCompletion even though, the Task is still running.

现在,让我们看看设置:

Now, let's see the setup:

// Start async.
Task t1 = Task.Factory.StartNew(Accept, s1);
Task t2 = Task.Factory.StartNew(Accept, s1);

Task.WhenAll(t1, t2).Wait();

Accept 方法:

public static async void Accept(object state)
{
    TcpListenerEx server = (TcpListenerEx) state;

    IPEndPoint endPoint = server.LocalEndpoint as IPEndPoint;

    Log("Accepting clients on {0}", endPoint);

    while (true)
    {
        var client = server.AcceptTcpClientAsync();

        if (client == null)
        {
            Log("Null error on accept");
            break;
        }

        TcpClient connected = (TcpClient) client;
        servers[server].Add(connected);

        bool stop = await Task<Task<bool>>.Factory.StartNew(Listen, connected).Unwrap();

        if (stop == true)
        {
            break;
        }
    }

    // Stop the server.
    server.Stop();

    Log("Stoppped {0}", endPoint);
}

由于 TaskStatus 更改为 RanToCompletion,Task.WhenAll().Wait() 调用标记自己很快完成,导致程序进一步执行,最终终止.

Because of TaskStatus changing to RanToCompletion, the Task.WhenAll().Wait() call marks itself finished fairly quickly, resulting in program to be executed further, eventually - terminated.

但是,Accept 任务理论上应该永远不会停止,它会监听连接直到明确停止.

But, the Accept task, in theory, should never stop, it's listening for connections until explicitly stopped.

这里是什么问题导致 Task 过早地被标记为 RanToCompletion?

What is the problem here that's causing the Task to be marked as RanToCompletion prematurely?

推荐答案

我可以用更少的代码重现这个问题:

I can reproduce this issue with far less code:

void Main()
{
    Task t1 = Task.Factory.StartNew(Accept);
    t1.Wait();
    Console.WriteLine("Main ended");
}

public static async void Accept()
{
    while (true)
    {
        await Task.Delay(1000);
    }

    Console.WriteLine("Stoppped");
}

但这可以正常工作:

void Main()
{
    Task t1 = Accept();
    t1.Wait();
    Console.WriteLine("Main ended");
}

public static async Task Accept()
{
    while (true)
    {
        await Task.Delay(1000);
    }

    Console.WriteLine("Stoppped");
}

基本上,通过使用 Task.Factory.StartNew(),您将创建一个 Task 基于一个单独的线程来调用给定的委托(Task>Accept() 方法).Accept 方法本身(就像任何好的 async 方法一样)实际上立即返回.所以调用它的线程会立即完成它的任务,所以为代表该线程而创建的 Task 也会立即完成.

Basically, by using Task.Factory.StartNew(), you are creating a Task based on a separate thread getting spawned to invoke the given delegate (the Accept() method). The Accept method itself (like any good async method) actually returns immediately. So the thread that calls it finishes its task immediately, so the Task created to represent that thread also finishes immediately.

如果你允许 Accept() 返回一个 Task 而不是 void,那么它的 Task如果您想等到它运行完所有 await s,则返回是您应该等待的.

If you allow Accept() to return a Task instead of void, then the Task that it returns is what you should be awaiting if you want to wait until it has run through all its awaits.

这篇关于如果任务等待的东西,任务状态更改为 RanToCompletion的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆