我有以下功能:
public static void StartWithErrorLogging(Func<Task> task, IAresLogger logger, CancellationToken token = default(CancellationToken))
{
new Task(async () =>
{
try
{
await task.Invoke();
}
catch (Exception e)
{
logger?.Log(LogMessageSeverity.Error, e.Message, e);
}
}, token).Start();
}
使用以下代码调用:
ErrorLoggedTask.StartWithErrorLogging(async () => await _recentSearchRepository.InsertAsync(new RecentSearch
{
AuthUserId = user.Subject.UserAuthId,
SearchDate = DateTimeOffset.Now,
SearchText = filter.SearchTerm
}, token), _logger, token);
有时会引发以下异常:
{ “exception”:“System.InvalidOperationException:可能不会调用Start 已完成的任务。\ r \ n在
中的System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r \ n
System.Threading.Tasks.Task.Start(TaskScheduler scheduler)\ r \ n at
Ares.Core.Scheduling.ErrorLoggedTask.StartWithErrorLogging(Func`1任务, IAresLogger记录器,CancellationToken令牌) C:\ .. \ ErrorLoggedTask.cs:第15行\ r \ n在
Ares.Api.Controllers.SearchController.d__17.MoveNext()in C:\ ... \ SearchController.cs:第97行\ r \ n ---结尾 从抛出异常的先前位置堆栈跟踪--- \ r \ n在
InvalidOperationException:可能无法在已完成的任务上调用Start
我能做些什么?
答案 0 :(得分:1)
You should never use the Task
constructor.
使用Task.Run
直接翻译代码的方式如下:
public static void StartWithErrorLogging(Func<Task> task, IAresLogger logger)
{
Task.Run(async () =>
{
try
{
await task.Invoke();
}
catch (Exception e)
{
logger?.Log(LogMessageSeverity.Error, e.Message, e);
}
});
}
(我删除了CancellationToken
,因为it most likely wasn't doing anything useful anyway)。实际上,如果在调用CancellationToken
之前取消Start
,则您发布的代码只会导致该异常。
但是,您几乎肯定不应该使用此代码,因为它是fire-and-forget on the threadpool, which is an antipattern on ASP.NET。