我有以下代码,其中延续代码未得到执行。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Konsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main starting...");
Task.Run(async () =>
{
await Job1();
})
.ContinueWith(async t =>
{
await Job2();
}).Wait();
Console.WriteLine("Main ending...");
}
public static async Task Job1()
{
await Task.Run(() =>
{
for (int i = 1; i <= 2; i++)
{
Thread.Sleep(1000);
Console.WriteLine($"Job1 {i}");
}
});
}
public static async Task Job2()
{
await Task.Run(() =>
{
for (int i = 1; i <= 2; i++)
{
Thread.Sleep(1000);
Console.WriteLine($"Job2 {i}");
}
});
}
}
}
控制台输出:
Main starting... Job1 1 Job1 2 Main ending...
我希望Job2也能在应用程序关闭之前执行。
答案 0 :(得分:4)
要回答您的问题,您需要从第一个异步调用中“解包”任务,如下所示:
Task.Run(async () =>
{
await Job1();
})
.ContinueWith(async t =>
{
await Job2();
})
.Unwrap()
.Wait();
不过,这里还有很多其他事情要评论。
如果您正在使用async / await,则应该一直使用它。您的问题没有指定您正在使用哪个版本的C#。如果您使用的是C# 7.1 or above,则应将main方法设为异步方法,如下所示:
public static async Task Main()
{
Console.WriteLine("Main starting...");
await Job1();
await Job2();
Console.WriteLine("Main ending...");
}
此外,正如@Sean指出的那样,Thread.Sleep
在这些情况下不是一个好主意,您应该改用await Task.Delay(1000);
。
Task.Delay Documentation
在MSDN上也可以找到一篇不错的文章,其中包含一些异步/等待最佳实践。
答案 1 :(得分:1)
You should not use ContinueWith
; it's a dangerous, low-level method。在这种情况下,您会遇到问题,因为ContinueWith
无法理解异步委托。
理想情况下,您应将所有对ContinueWith
(和Wait
)的呼叫替换为await
:
static async Task Main(string[] args)
{
Console.WriteLine("Main starting...");
await Task.Run(async () =>
{
await Job1();
});
await Job2();
Console.WriteLine("Main ending...");
}
如果您对变量进行分解以便可以看到类型,则会更加清楚为什么原始代码不起作用:
static async Task Main(string[] args)
{
Console.WriteLine("Main starting...");
Task runTask = Task.Run(async () =>
{
await Job1();
});
Task<Task> continuationTask = runTask.ContinueWith(async t =>
{
await Job2();
});
// continuationTask is a Task<Task>.
// This waits for the "outer" task only, not the "inner" task.
continuationTask.Wait();
Console.WriteLine("Main ending...");
}