【发布时间】:2017-01-10 07:31:48
【问题描述】:
我在书本的基础上学习使用线程。
我想等待我的任务和它的继续工作。但是我在“BLEEEEEEEEEEEEEEEEP”之前看到了 “Press any key for exit...”消息(请查看我的代码的 cmets)。为什么会发生,我该如何解决?
我知道我可以使用两个任务并为每个任务使用Task.Wait(),但是如果我需要为延续对象做同样的事情怎么办?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Bushman.Sandbox.Threads {
class Program {
static void Main(string[] args) {
Console.Title = "Threads";
try {
// The main work
Action act1 = () => {
for (int i = 0; i < 10; i++) {
int id = Thread.CurrentThread
.ManagedThreadId;
Console.WriteLine(
"bleep. Thread Id: {0}",
id.ToString());
}
};
// This operation is to be done when the main
// work will be finished.
Action act2 = () => {
int id = Thread.CurrentThread
.ManagedThreadId;
Console.WriteLine(
"bleep. Thread Id: {0}",
id.ToString());
Console.WriteLine(
"BLEEEEEEEEEEEEEEEP. Thread Id: {0}",
id.ToString());
};
Task task = new Task(act1);
var awaiter = task.GetAwaiter();
awaiter.OnCompleted(act2);
Console.WriteLine("Work started...");
task.Start();
// TODO: wait while both actions will be done
task.Wait(); // it doesn't work as I expected
// it doesn't work as I expected too...
awaiter.GetResult();
}
catch (Exception ex) {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
Console.ResetColor();
}
Console.WriteLine("Press any key for exit...");
Console.ReadKey();
}
}
}
【问题讨论】:
-
我想
OnCompleted动作在另一个线程/任务中被触发,因此,不能保证该线程或主线程中的Console.WriteLine是否会首先触发. -
另外,查看
TaskAwaiter类的 MSDN 文档,它的用途是用于编译器,而不是直接用于代码。你为什么用它而不是task.Wait()?task.Wait()怎么没有达到你的预期? -
@Abion47,您可能有兴趣阅读此blog.stephencleary.com/2014/12/… 以了解为什么有时更喜欢使用 GetAwaiter().GetResult() 而不是 Wait()。
-
@Evk 我不确定我是否理解其中的原因。似乎唯一的好处是它不会将任务引发的异常包装在
AggregateException中,但解包异常似乎只是一个方便的问题(我仍然可以完全落后,但仍然如此)。似乎该博客文章建议不要使用TaskAwaiter或Task.Wait(),而是在99.99%的情况下更喜欢使用await(并且不清楚0.01的哪一部分% 的案例构成不使用它)。 -
@Abion47 当然,如果你可以使用 await - 你应该这样做。但是,在某些情况下您不能并且应该阻止(一个示例是当您需要同步执行但您使用的 API 仅提供异步版本时,这种情况现在经常发生)。在这种情况下(这种情况确实会发生,即使很少见),您可能更喜欢 GetAwaiter().GetResult() 而不是 AggregateException。无论如何不能有一个以上的异常,所以没有理由费心从 AggregateException 中解压那个异常。当然,正如您所说,这是为了方便。
标签: c# .net multithreading task