我有控制台应用程序,我有两个步骤。 Step1 和 Step2 。我希望 Step 1 在主线程上运行,而 Step 2 在后台的不同线程上运行,我正在使用C# task object
。
见下面的代码片段:
public static Task PrintCount()
{
Console.WriteLine("Step 2");
for (var i = 1; i <= 1000; i++)
{
Thread.Sleep(1000);
Console.WriteLine(i);
}
return Task.FromResult(0);
}
static void Main(string[] args)
{
Task.Run(() => PrintCount());
Console.WriteLine("Step 1");
Console.Read();
}
此完美正常如果我使用 Task.Run().
当我没有使用它时,如下所述,它作为同步操作运行。
var taskResult = PrintCount();
在这种情况下, Step 2 将首先执行,完成1000的迭代直到方法完成,然后它将执行 Step 1 。
问题是 - 如何在不使用Task.Run()的情况下运行第2步方法,我仍然希望在不同的线程上以异步方式运行第2步方法。
我相信是 PrintCount()
返回Task
对象,如果我们不等待它,它将异步运行,但它不是那样的。
请问您如何在不使用Task.Run()的情况下使用DoSomehing()
方法在不同的线程上运行Task
。
提前致谢!
更新
public static async Task PrintCount()
{
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine("Step 2");
for (var i = 1; i <= 1000; i++)
{
Thread.Sleep(1000);
Console.WriteLine(i);
}
}
这将在另一个线程上运行。
我如何调用它没有变化。
var taskResult = PrintCount();
答案 0 :(得分:1)
如何在不使用Task.Run()
的情况下在单独的线程上运行C#任务方法好吧,为什么我不想使用Task.Run()因为我相信如果一个方法返回任务对象并且我们没有等待,它将在不同的线程上运行,因为我们已经不等待它的结果。有点火与忘记。
如果你不await
Task.Run
从await
返回的任务,那么是的,它就是一次又一次的冒险。解决方案是Task.Run
从public static void PrintCount()
{
Console.WriteLine("Step 2");
for (var i = 1; i <= 1000; i++)
{
Thread.Sleep(1000);
Console.WriteLine(i);
}
}
static async Task Steps()
{
var task = Task.Run(() => PrintCount());
Console.WriteLine("Step 1");
await task;
}
返回的任务:
Main
您的Main
可能看起来像这样,但我通常建议开发人员使用除控制台应用之外的其他内容,以及&#34;尝试&#34;异步。因为static void Main()
{
Steps().GetAwaiter().GetResult();
Console.Read();
}
应该阻止任务,但通常应该避免阻止异步任务:
$rule = [
['institutionID', '=', $instID],
['acadCareerID', '=', $acadID],
['termID', '=', $termID],
['departmentID', '=', $depID]
];
答案 1 :(得分:1)
PrintCount
的第一次实现确实是同步的,因为这就是你编写它的方式。当你调用方法时,它只是开始执行每行代码,点击Thread.Sleep
调用并阻塞线程,直到它们各自完成,直到最后,最后,返回已经完成的Task
。 / p>
避免使用Task.Run
的方法是对任何长时间运行的操作使用固有异步操作。在你的情况下,你实际上没有任何长期运行的CPU绑定工作;你唯一长时间运行的等待一秒钟。要在固定的时间段内不执行任何操作,请使用Task.Delay
。因此,如果您将Thread.Sleep(...)
的用法替换为await Task.Delay(...)
,则操作将变为固有异步,并且赢得了&#39;需要使用Task.Run
来执行此操作。
在第二个实现中,您确实演示了Task.Delay
的适当用法,但在等待异步操作之后,您只需使用Thread.Sleep
调用阻止该线程一段时间。这是阻塞线程,而它什么都不做,就像之前一样,但区别在于代码在线程池线程中运行,因为它位于await
之后。 await
表示方法的其余部分将在等待Task
完成之后的某个稍后点运行,并且完成的方式是让当前线程继续运行并且然后让一个线程池线程运行该方法的其余部分,当它能够运行时。请注意,如果存在SynchronizationContext集,那么将用于运行continuation,而不是线程池线程。
答案 2 :(得分:-1)
创建的Task
对象只是要完成的任务的描述。 Task
本身在您安排之前不会执行,无论是使用静态Task.Run()
方法还是使用task.Start()
实例方法。