InvalidOperationException:可能无法在已完成

时间:2018-01-24 13:48:35

标签: c#

我有以下功能:

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.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在
      

中的System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r \ n      

InvalidOperationException:可能无法在已完成的任务上调用Start

我能做些什么?

1 个答案:

答案 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