在新后台线程中执行任务



我知道有一百万个问题,我正在尝试他们的解决方案,但它似乎没有像我预期的那样表现。

使用以下代码:

await Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("I'm running after Thread.Sleep"); });
Console.WriteLine("I'm running after Task.Run");

我得到输出:

[ 5 seconds elapses ]
I'm running after Thread.Sleep
I'm running after Task.Run

这与我在不使用Task.Run的情况下获得的输出相同

我想要的是输出:

I'm running after Task.Run
[ 5 seconds elapses ]
I'm running after Thread.Sleep

"父"线程的执行继续,长时间运行的任务以不影响"父"线程的方式"在后台"执行。

如前所述,您需要删除await但是,这会将其变成一个即发即弃的任务,如果上面的代码恰好在控制台应用程序的Main中,那么您的进程可能会在任务完成之前终止。

好:

// C# 7
static async void Main(string[] args) // <--- note `async` signature
{
await Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("I'm running 
after Thread.Sleep"); });
Console.WriteLine("I'm running after Task.Run");
}

不好:- 未await的即发即弃任务

static void Main(string[] args)
{
Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("Spider Man: I don't wan't to go!"); });  // POOF!! 
Console.WriteLine("I'm running after Task.Run");
// sorry Spidy, you're dead
}

因此,即使您有Thread.Sleep(),也可能根本看不到I'm running after Thread.Sleep。(顺便说一下,你应该使用Task.Delay())。 您可以通过Console.ReadKey()来缓解它,但这可能会破坏目的。

即发即弃任务有其用途,并且可以在其他类型的长时间运行的应用程序(如 WinForms)中合理安全地使用,但人们通常不会在流程的入口点生成任务,因此任务通常会运行到完成,而不会被进程提前终止。 但是,通常最好尽可能使用await,这样您就不会在脚上开枪。

此外,你对事物按特定顺序的要求表明了对async/await如何运作的误解。

使用await时要记住的一件事是代码等待对象。这些对象就像任何其他对象一样。具体来说,它们可以分配给局部变量或类变量。

所以,这段代码:

await Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("I'm running after Thread.Sleep"); });
Console.WriteLine("I'm running after Task.Run");

本质上与此代码相同:

var task = Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("I'm running after Thread.Sleep"); });
await task;
Console.WriteLine("I'm running after Task.Run");

换句话说:

  1. 启动在后台线程上运行的任务。
  2. 异步等待 (await) 完成该任务。
  3. 显示"I'm running after Task.Run".

所以输出是预期的。

我想要的是输出:

我在 Task.Run 之后运行

[ 5 秒过去 ]

我正在 Thread.Sleep 之后运行

在这种情况下,请启动在后台线程上运行的任务,但要等到以后才await它:

var task = Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("I'm running after Thread.Sleep"); });
Console.WriteLine("I'm running after Task.Run");
await task;

如果你想异步运行,你应该删除命令

static void Main(string[] args)
{
Task.Run(() => { Thread.Sleep(5000); Console.WriteLine(DateTime.Now + " => I'm running after Thread.Sleep"); });
Console.WriteLine(DateTime.Now + " => I'm running after Task.Run");
while (true)
{
Thread.Sleep(500);
}
}

输出 28/05/2019 09:49:58 => I'm running after Task.Run 28/05/2019 09:50:03 => I'm running after Thread.Sleep

最新更新