如何在Quartz计划任务中同步调用异步方法

8

我正在尝试从我的quartz.net定时作业调用一个webapi方法。我不确定我所做的方式是否正确?有人能帮忙确认这是否是正确的方式,或者是否有更好的方法可用吗?

MethodRepository.cs

public async Task<IEnumerable<ResultClass>> GetResult(string queryCriteria)
{
    return await _httpClient.Get(queryCriteria);
}

Quartz任务:

public async void Execute(IJobExecutionContext context)
{
    var results= await _repo.GetResult();
}

通用Httpclient:

public async Task<IEnumerable<T>> Get(string queryCriteria)
{
    _addressSuffix = _addressSuffix + queryCriteria;
    var responseMessage = await _httpClient.GetAsync(_addressSuffix);
    responseMessage.EnsureSuccessStatusCode();
    return await responseMessage.Content.ReadAsAsync<IEnumerable<T>>();
}

但是Quartz文档说我不能在Quartz作业中使用异步方法。那么Web API方法怎么办呢?

我可以将Quartz作业执行方法更改为:

public void Execute(IJobExecutionContext context)
{
    var result = _repo.GetResult().Result;
}

2个回答

22

Quartz.NET 3.0 可以直接支持 async/await。因此,您现在可以(也必须)将 Execute 方法声明为返回 Task,并使用 async/await。

public async Task Execute(IJobExecutionContext context)
{
    var result = await _repo.GetResult();
}

4
如果必须这样做,那么是的,你可以这样做,但它会阻塞调用线程,直到异步操作完成。 Task.Result 将任何异常封装成 AggregateException。
因此,你应该在 try catch 中放置你的 httpclient 调用。
  try
  {
      var result = _repo.GetResult().Result;
  }
  catch (AggregateException ae)
  {
      // handle exception
  }

此外,他们似乎正在开发一个 异步作业

2
在你真正需要它(并且能够处理像 OutOfMemoryException 这样的异常)之前,捕获所有异常并不是一个好主意。更糟糕的是过滤和重新抛出其中一些或嵌套的异常。你可以通过使用 task.GetAwaiter().GetResult() 方法轻松避免这种情况,该方法可以帮助你摆脱 AggregateException 并处理原始异常。 - lorond
1
当然。只是提醒一下,Task.Result 会引发 AggregateException 异常 - 没有其他意思。 - William Xifaras
@lorond,根据Quartz最佳实践,您实际上应该在作业内处理所有异常,因此我认为这算是“真正需要的”。 - alpha-mouse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接