我正在尝试在不等待结果的情况下调用异步方法(在ASP.NET Web API 2应用程序中)。我的意思是我希望主线程继续执行并且不等待被调用的方法来完成。我正在尝试这个片段:
// The async method:
private static async Task LogAsync(Exception exception, string ip, MethodBase method, object parameters) {
// some stuff
}
// The caller methods:
public static void Log1(Exception exception, object parameters) {
LogAsync(exception, ip, method, parameters);
}
public static void Log2(Exception exception, object parameters) {
Task.Factory.StartNew(() => LogAsync(exception, ip, method, parameters));
}
public static async void Log3(Exception exception, object parameters) {
await LogAsync(exception, ip, method, parameters).ConfigureAwait(true);
}
public static async void Log4(Exception exception, object parameters) {
// I've tried even this one:
await LogAsync(exception, ip, method, parameters).ConfigureAwait(false);
}
正如你所看到的,我尝试了不同的方式;但没有他们给我我想要的东西。你有什么想法,对我有什么帮助?
答案 0 :(得分:9)
我正在尝试调用异步方法(在ASP.NET Web API 2应用程序中)而不等待结果。
你确定这是你想做的吗?在ASP.NET上,如果你启动这样的独立工作(即,工作与HTTP请求无关),那么这项工作可能会在你不知情的情况下中止。在这种情况下,您的方法称为“日志”,因此可能是异步日志记录。所以你只想避免 await
如果偶尔丢失日志是完全可以接受的。如果您希望日志可靠,则需要保留await
。你的电话。
假设偶尔丢失日志是可以的,那么您至少应该使用ASP.NET运行时注册工作。如果您使用的是.NET 4.5.2,则可以使用HostingEnvironment.QueueBackgroundWorkItem
:
public static void Log(Exception exception, object parameters) {
HostingEnvironment.QueueBackgroundWorkItem(_ =>
LogAsync(exception, ip, method, parameters));
}
如果您使用的是旧版本的.NET(4.5或4.5.1),则可以使用我的AspNetBackgroundTasks library:
public static void Log(Exception exception, object parameters) {
BackgroundTaskManager.Run(() =>
LogAsync(exception, ip, method, parameters));
}
两者之间的语义略有不同(我有一个写on my blog),但它们都注册了ASP.NET运行时的工作,所以至少它不是完全不可靠的Task.Factory.StartNew
或Task.Run
是。
答案 1 :(得分:0)
你做得对。
第一种方法就是你需要的。
// The caller methods:
public static void Log1(Exception exception, object parameters) {
LogAsync(exception, ip, method, parameters);
}
问题可能出在其他地方。你是如何测试的?
Log1的LogAsync
将在不同的线程上执行。这就像火与忘记,这正是你所需要的。
编辑: 尝试将LogAsync方法更改为:
// The async method:
private static void LogAsync(Exception exception, string ip, MethodBase method, object parameters) {
Task.Factory.StartNew(delegate {
// some stuff });
}