GetAwaiter 无法等待 Quartz 库的 Clear 方法完成 - Quartz 中是否存在错误或我的理解存在差距?
GetAwaiter not working to wait for the completion of Quartz library's Clear method - is there a bug in Quartz or a gap in my understanding?
最新版本的 Quartz 库将所有内容切换为使用 async/await。调用应用程序具有非常嵌入框架中的同步调用,所以我一直在调用 .GetAwaiter()(我知道这并不理想。它是一个控制台应用程序,因此由于只有一个 UI 线程而导致的死锁应该不会发生。)
我需要清除计划数据库,等待清除命令完成,并在某些情况下重新填充数据库。我在 Quartz 的 Clear 方法上调用 .GetAwaiter(),但它不会等待 - 也就是说,.GetAwaiter 行之后的下一行在所有应该等待的代码之前运行。
我想有很多工作(并且没有性能优势,因为我无论如何都需要 .GetAwaiter() )我可以重构至少调用 Clear() 和从同一个异步方法安排更多作业的方法,并在更高级别调用 .GetAwaiter(),但我不确定这是否可行 - 如果 .GetAwaiter() 没有按预期等待,"await" 会更好吗?
当然我可以编写自己的 sql 调用来直接清除数据库,最后我可能不得不这样做,但是当 Quartz 有一个清除其调度程序上的方法。
我对 Quartz 调度程序的 Clear 方法的调用非常简单:
myScheduler.Clear().GetAwaiter();
我发现在 Quartz 的 StdAdoDelegate.ClearData 方法中的代码之前被调用的代码行,我认为我的 GetAwaiter() 调用会阻止这种情况。这是 Quartz 中的错误吗?如果是,Quartz 库的代码有什么问题?还是我的想法有问题?
调用 Quartz 的 Clear() 方法时调用的代码概要如下:
StdScheduler:
Task Clear(cancellationToken)
return sched.Clear(cancellationToken);
QuartzScheduler:
async Task Clear(cancellationToken = default)
await resources.JobStore.ClearAllSchedulingData(cancellationToken).ConfigureAwait(false);
JobStoreSupport:
Task ClearAllSchedulingData
return ExecuteInLock(LockTriggerAccess, conn => ClearAllSchedulingData(conn, cancellationToken), cancellationToken);
async Task ExecuteInLock(lockName, txCallback, cancellationToken=default)
await ExecuteInLock<object>(lockName, async conn =>
{
await txCallback(conn).ConfigureAwait(false);
return null;
}, cancellationToken).ConfigureAwait(false);
JobStoreTX (which inherits from JobStoreSupport):
Task<T> ExecuteInLock<T>(lockName, txCallback, cancellationToken)
return ExecuteInNonManagedTXLock(lockName, txCallback, cancellationToken);
JobStoreSupport:
Task<T> ExecuteInNonManagedTXLock(lockName, txCallback, cancellationToken)
T result = await txCallback(conn).ConfigureAwait(false);
(stack trace returns first to ExecuteInLock<T>, then to ExecuteInLock, and then to ClearAllSchedulingData as callback is called)
async Task ClearAllSchedulingData(conn, cancellationToken)
await Delegate.ClearData(conn, cancellationToken).ConfigureAwait(false);
StdAdoDelegate:
async Task ClearData(conn, cancellationToken=default)
DbCommand ps = PrepareCommand(conn, ReplaceTablePrefix(SqlDeleteAllSimpleTriggers));
await ps.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
ps = PrepareCommand(conn, ReplaceTablePrefix(SqlDeleteAllSimpropTriggers));
await ps.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
And more similar calls...
非常感谢您的帮助!!
.GetAwaiter()
只有returns一个TaskAwaiter
,你需要向等待者请求结果,即使它只是一个带有none的任务(void
) 结果类型。要等待任务完成,只需调用:myScheduler.Clear().GetAwaiter().GetResult();
最新版本的 Quartz 库将所有内容切换为使用 async/await。调用应用程序具有非常嵌入框架中的同步调用,所以我一直在调用 .GetAwaiter()(我知道这并不理想。它是一个控制台应用程序,因此由于只有一个 UI 线程而导致的死锁应该不会发生。)
我需要清除计划数据库,等待清除命令完成,并在某些情况下重新填充数据库。我在 Quartz 的 Clear 方法上调用 .GetAwaiter(),但它不会等待 - 也就是说,.GetAwaiter 行之后的下一行在所有应该等待的代码之前运行。
我想有很多工作(并且没有性能优势,因为我无论如何都需要 .GetAwaiter() )我可以重构至少调用 Clear() 和从同一个异步方法安排更多作业的方法,并在更高级别调用 .GetAwaiter(),但我不确定这是否可行 - 如果 .GetAwaiter() 没有按预期等待,"await" 会更好吗?
当然我可以编写自己的 sql 调用来直接清除数据库,最后我可能不得不这样做,但是当 Quartz 有一个清除其调度程序上的方法。
我对 Quartz 调度程序的 Clear 方法的调用非常简单:
myScheduler.Clear().GetAwaiter();
我发现在 Quartz 的 StdAdoDelegate.ClearData 方法中的代码之前被调用的代码行,我认为我的 GetAwaiter() 调用会阻止这种情况。这是 Quartz 中的错误吗?如果是,Quartz 库的代码有什么问题?还是我的想法有问题?
调用 Quartz 的 Clear() 方法时调用的代码概要如下:
StdScheduler:
Task Clear(cancellationToken)
return sched.Clear(cancellationToken);
QuartzScheduler:
async Task Clear(cancellationToken = default)
await resources.JobStore.ClearAllSchedulingData(cancellationToken).ConfigureAwait(false);
JobStoreSupport:
Task ClearAllSchedulingData
return ExecuteInLock(LockTriggerAccess, conn => ClearAllSchedulingData(conn, cancellationToken), cancellationToken);
async Task ExecuteInLock(lockName, txCallback, cancellationToken=default)
await ExecuteInLock<object>(lockName, async conn =>
{
await txCallback(conn).ConfigureAwait(false);
return null;
}, cancellationToken).ConfigureAwait(false);
JobStoreTX (which inherits from JobStoreSupport):
Task<T> ExecuteInLock<T>(lockName, txCallback, cancellationToken)
return ExecuteInNonManagedTXLock(lockName, txCallback, cancellationToken);
JobStoreSupport:
Task<T> ExecuteInNonManagedTXLock(lockName, txCallback, cancellationToken)
T result = await txCallback(conn).ConfigureAwait(false);
(stack trace returns first to ExecuteInLock<T>, then to ExecuteInLock, and then to ClearAllSchedulingData as callback is called)
async Task ClearAllSchedulingData(conn, cancellationToken)
await Delegate.ClearData(conn, cancellationToken).ConfigureAwait(false);
StdAdoDelegate:
async Task ClearData(conn, cancellationToken=default)
DbCommand ps = PrepareCommand(conn, ReplaceTablePrefix(SqlDeleteAllSimpleTriggers));
await ps.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
ps = PrepareCommand(conn, ReplaceTablePrefix(SqlDeleteAllSimpropTriggers));
await ps.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
And more similar calls...
非常感谢您的帮助!!
.GetAwaiter()
只有returns一个TaskAwaiter
,你需要向等待者请求结果,即使它只是一个带有none的任务(void
) 结果类型。要等待任务完成,只需调用:myScheduler.Clear().GetAwaiter().GetResult();