我正在创建一个任务调度程序,所以我试图创建某种重复函数,接受任务并等待它但我得到一个奇怪的例外Type 'T' is not awaitable
public static Task<T> Interval<T>(TimeSpan pollInterval, Func<T> action, CancellationToken token)
{
return Task.Factory.StartNew(
async () =>
{
for (; ; )
{
if (token.WaitCancellationRequested(pollInterval))
break;
await action();
}
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
所以有人可以告诉我,我怎么能等待那个通用任务因为我希望函数接受任何Task,Task,bool或任何其他类型?
答案 0 :(得分:8)
您不需要为此启动长时间运行的任务 - 只需使您的方法直接异步:
public static async Task RunAtIntervalAsync(TimeSpan pollInterval, Action action, CancellationToken token)
{
while(true)
{
await Task.Delay(pollInterval, token);
action();
}
}
这将导致Action
在当前上下文中运行。如果不需要,您可以使用:
await Task.Delay(pollInterval, token).ConfigureAwait(false);
action();
这将导致Action
无法在调用者的同一同步上下文中运行,并可能使用ThreadPool线程。
编辑以回应评论:
如果您不希望结果任务取消,但只是在激活令牌时返回,您可以使用:
public static async Task RunAtIntervalAsync(TimeSpan pollInterval, Action action, CancellationToken token)
{
while(!token.IsCancellationRequested)
{
try
{
await Task.Delay(pollInterval, token);
action();
}
catch(OperationCanceledException e)
{
// Swallow cancellation - dangerous if action() throws this, though....
break;
}
}
}
编辑2:
如果你想传递async
lambdas,你应该让方法采用Func<Task>
,而不是Action
:
public static async Task RunAtIntervalAsync(TimeSpan pollInterval, Func<Task> actionTask, CancellationToken token)
{
while(!token.IsCancellationRequested)
{
try
{
await Task.Delay(pollInterval, token);
}
catch(OperationCanceledException e)
{
// Swallow cancellation
break;
}
await actionTask();
}
}
编辑以回应聊天:
如果您想轮询,但使用操作的结果,您可以使用:
public static async Task RunAtIntervalAsync<T>(TimeSpan pollInterval, Func<Task<T>> fetchOperation, Action<T> operationOnResult, CancellationToken token)
{
while(!token.IsCancellationRequested)
{
try
{
await Task.Delay(pollInterval, token);
}
catch(OperationCanceledException e)
{
// Swallow cancellation
break;
}
// Get a value
T value = await fetchOperation();
// Use result (ie: update UI)
operationOnResult(value);
}
}
然后您可以通过以下方式调用此方法:
RunAtIntervalAsync(TimeSpan.FromSeconds(1),
async () => { await Task.Delay(1000); return "Foo"; },
result => UpdateUI(result),
token);
答案 1 :(得分:5)
你不能。
你可以创建一个带有泛型异步功能的函数 - 一个返回Task<T>
的函数。
那将是Func<Task<T>>
。
您还可以创建一个具有通用同步功能的功能,这就是您现在拥有的功能。
您不能创建一个可以执行任何操作的函数,但是您可以进行两次重载。
在不相关的注释中,您的函数实际上从未使用函数的返回值
因此,你根本不应该把它变成通用的;您应该选择Func<Task>
或Action
。
答案 2 :(得分:0)