在新的后台线程中执行任务

Fra*_*ayt 0 c# multithreading asynchronous

我知道对此有上百万个问题,我正在尝试他们的解决方案,但是它似乎并没有我期望的那样。

使用以下代码:

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

我得到的输出:

[ 5 seconds elapses ]
I'm running after Thread.Sleep
I'm running after Task.Run
Run Code Online (Sandbox Code Playgroud)

如果不使用,我将获得相同的输出 Task.Run

我想要的是输出:

I'm running after Task.Run
[ 5 seconds elapses ]
I'm running after Thread.Sleep
Run Code Online (Sandbox Code Playgroud)

在继续执行“父”线程的情况下,长时间运行的任务在“后台”执行的方式不影响“父”线程。

Mic*_*kyD 5

如前所述,您需要删除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");
 }
Run Code Online (Sandbox Code Playgroud)

坏: -没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
 }
Run Code Online (Sandbox Code Playgroud)

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

即弃任务有其用途,可以合理地安全地用于其他类型的长期运行的应用程序中,例如WinForms,但人们通常不会在流程的入口点生成任务,因此任务通常无需任何操作即可完成提前终止流程。但是,通常在可能的情况下使用它是个好主意,await这样就不会在脚上开枪。

同样,您以某种顺序想要事物的要求表明了对async/await工作原理的误解。


Ste*_*ary 5

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

所以,这段代码:

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

本质上与此代码相同:

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");
Run Code Online (Sandbox Code Playgroud)

换句话说:

  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;
Run Code Online (Sandbox Code Playgroud)