异步总是WaitingForActivation

时间:2013-12-29 22:53:15

标签: c# .net asynchronous async-await

我想知道async& await个关键字都是关键,但输出并不是我所期望的。

控制台应用程序如下:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Foo called");
        var result = Foo(5);

        while (result.Status != TaskStatus.RanToCompletion)
        {
            Console.WriteLine("Thread ID: {0}, Status: {1}", Thread.CurrentThread.ManagedThreadId, result.Status);
            Task.Delay(100).Wait();
        }

        Console.WriteLine("Result: {0}", result.Result);
        Console.WriteLine("Finished.");
        Console.ReadKey(true);
    }

    private static async Task<string> Foo(int seconds)
    {
        return await Task.Run(() =>
            {
                for (int i = 0; i < seconds; i++)
                {
                    Console.WriteLine("Thread ID: {0}, second {1}.", Thread.CurrentThread.ManagedThreadId, i);
                    Task.Delay(TimeSpan.FromSeconds(1)).Wait();
                }

                return "Foo Completed.";
            });
    }
}

输出结果为:

Foo called
Thread ID: 10, Status: WaitingForActivation
Thread ID: 6, second 0.
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 6, second 1.
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 6, second 2.
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 6, second 3.
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 6, second 4.
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Thread ID: 10, Status: WaitingForActivation
Result: Foo Completed.
Finished..

一旦方法启动,我希望看到状态从WaitingForActivation更改。

它如何保持这种状态并保持活跃状态​​?

5 个答案:

答案 0 :(得分:51)

对于我的回答,值得记住的是,在async-await关键字和async-await关键字之前引入了TPL(Task-Parallel-Library),Task类和TaskStatus枚举不是TPL的原始动机。

在标记为async的方法的上下文中,结果Task不是表示方法执行的Task,而是Task表示方法的延续方法。

这只能使用几种可能的状态:

  • 取消
  • 断陷
  • RanToCompletion
  • WaitingForActivation

我理解Running似乎是一个比WaitingForActivation更好的默认值,但这可能会产生误导,因为大多数情况下,执行的异步方法实际上并没有运行(即它可能是await - 其他东西)。另一个选项可能是向TaskStatus添加新值,但这可能是现有应用程序和库的重大变化。

所有这些都与使用Task.Run时非常不同,TaskStatus是原始TPL的一部分,这可以使用IProgress(T)枚举的所有可能值。

如果您希望跟踪异步方法的状态,请查看IProgress(T)界面,这样您就可以报告正在进行的进度。此博文Async in 4.5: Enabling Progress and Cancellation in Async APIs将提供有关{{1}}界面使用的更多信息。

答案 1 :(得分:18)

原因是您的result已分配给返回的Task,表示方法的继续,并且您的方法中有一个不同的任务正在运行,如果您像这样直接分配任务,你将获得预期的结果:

var task = Task.Run(() =>
        {
            for (int i = 10; i < 432543543; i++)
            {
                // just for a long job
                double d3 = Math.Sqrt((Math.Pow(i, 5) - Math.Pow(i, 2)) / Math.Sin(i * 8));
            }
           return "Foo Completed.";

        });

        while (task.Status != TaskStatus.RanToCompletion)
        {
            Console.WriteLine("Thread ID: {0}, Status: {1}", Thread.CurrentThread.ManagedThreadId,task.Status);

        }

        Console.WriteLine("Result: {0}", task.Result);
        Console.WriteLine("Finished.");
        Console.ReadKey(true);

output

enter image description here

请考虑这一点以获得更好的解释:您有一个Foo方法,让我们说任务A ,并且您有一个Task ,让我们说任务B ,现在正在运行任务,任务B ,您的任务A 等待< strong>任务B结果。您将结果变量分配给返回的Task 任务A,,因为任务B未返回任务,它返回string。考虑一下:

如果您定义结果如下:

Task result = Foo(5);

你不会得到任何错误。但是如果你这样定义:

string result = Foo(5);

你会得到:

无法将类型'System.Threading.Tasks.Task'隐式转换为'string'

但是,如果您添加await关键字:

string result = await Foo(5);

再次你不会得到任何错误。因为它会等待结果(字符串)并将其分配给你的结果变量。如果你在你的Foo方法中添加两个任务,最后要考虑这个:

private static async Task<string> Foo(int seconds)
{
    await Task.Run(() =>
        {
            for (int i = 0; i < seconds; i++)
            {
                Console.WriteLine("Thread ID: {0}, second {1}.", Thread.CurrentThread.ManagedThreadId, i);
                Task.Delay(TimeSpan.FromSeconds(1)).Wait();
            }

            // in here don't return anything
        });

   return await Task.Run(() =>
        {
            for (int i = 0; i < seconds; i++)
            {
                Console.WriteLine("Thread ID: {0}, second {1}.", Thread.CurrentThread.ManagedThreadId, i);
                Task.Delay(TimeSpan.FromSeconds(1)).Wait();
            }

            return "Foo Completed.";
        });
}

如果您运行该应用程序,您将获得相同的结果。(WaitingForActivation)因为现在,您的任务A正在等待这两项任务。

答案 2 :(得分:1)

此代码似乎为我解决了这个问题。它是针对流类的,因此是一些术语。

*ngFor

答案 3 :(得分:0)

我有同样的问题。答案使我步入正轨。因此,问题在于带有异步标记的函数不会按预期返回该函数本身的任务(而是该函数的另一个延续任务)。

因此它的“ await”和“ async”关键字使事情搞砸了。那么,最简​​单的解决方案就是删除它们。然后它按预期工作。如:

static void Main(string[] args)
{
    Console.WriteLine("Foo called");
    var result = Foo(5);

    while (result.Status != TaskStatus.RanToCompletion)
    {
        Console.WriteLine("Thread ID: {0}, Status: {1}", Thread.CurrentThread.ManagedThreadId, result.Status);
        Task.Delay(100).Wait();
    }

    Console.WriteLine("Result: {0}", result.Result);
    Console.WriteLine("Finished.");
    Console.ReadKey(true);
}

private static Task<string> Foo(int seconds)
{
    return Task.Run(() =>
    {
        for (int i = 0; i < seconds; i++)
        {
            Console.WriteLine("Thread ID: {0}, second {1}.", Thread.CurrentThread.ManagedThreadId, i);
            Task.Delay(TimeSpan.FromSeconds(1)).Wait();
        }

        return "Foo Completed.";
    });
}

哪个输出:

Foo called
Thread ID: 1, Status: WaitingToRun
Thread ID: 3, second 0.
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 3, second 1.
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 3, second 2.
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 3, second 3.
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 3, second 4.
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Thread ID: 1, Status: Running
Result: Foo Completed.
Finished.

答案 4 :(得分:-2)

如果有兴趣的话,我可以解决这个问题。 在myMain方法中,我调用了我的readasync方法,例如

Dispatcher.BeginInvoke(new ThreadStart(() => ReadData()));

现在一切对我来说都很好。