我想知道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
更改。
它如何保持这种状态并保持活跃状态?
答案 0 :(得分:51)
对于我的回答,值得记住的是,在async-await关键字和async-await关键字之前引入了TPL(Task-Parallel-Library),Task
类和TaskStatus
枚举不是TPL的原始动机。
在标记为async
的方法的上下文中,结果Task
不是表示方法执行的Task
,而是Task
表示方法的延续方法。
这只能使用几种可能的状态:
我理解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
:
请考虑这一点以获得更好的解释:您有一个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()));
现在一切对我来说都很好。