【发布时间】:2021-04-30 14:26:45
【问题描述】:
我构建了一种计划任务,它将在计划日期执行操作。我用Task.Delay(delay).ContinueWith(action.Invoke())
有时该操作会引发异常,但仍无法传播此异常以正确注册它。
在我的示例中,a 创建了一个包含三个文本的列表,空文本将引发异常,但是我无法在 try..catch 块中捕获此异常。
class Program
{
static async Task Main()
{
var texts = new List<string>() { "text 1", null, "text 2"};
foreach (var text in texts)
{
var scheduleDate = DateTime.UtcNow.AddSeconds(10);
try
{
ReminderControl.AddReminder(Print, text, scheduleDate);
}
catch (Exception ex)
{
Console.WriteLine($"Error to schedule the text {text} to be print on {scheduleDate:s}. ex: {ex.Message}");
}
}
while (true)
{
await Task.Delay(2000);
Console.WriteLine("Doing other things...");
}
}
static void Print(object text)
{
if (text is null)
throw new ArgumentNullException(); \\thrown , but not propagated out
Console.WriteLine(text);
}
}
public class ReminderControl
{
public static void AddReminder(Action<object> remiderCallback, object context, DateTime scheduleDate)
{
var delay = scheduleDate.Subtract(DateTime.UtcNow);
Task.Delay(delay)
.ContinueWith(t => remiderCallback.Invoke(context));
//.ContinueWith(t => throw t.Exception, TaskContinuationOptions.OnlyOnFaulted); even with this line the exception still does not propagate
}
}
在 Task.Delay 中使用 await 更新
await ReminderControl.AddReminder(Print, text, scheduleDate);
public static async Task AddReminder(Action<object> remiderCallback, object context, DateTime scheduleDate)
{
var delay = scheduleDate.Subtract(DateTime.UtcNow);
await Task.Delay(delay);
remiderCallback.Invoke(context);
}
之后,try..catch 块捕获了异常,但是,"Doing other things..." 停止打印,可能正在等待 AddRemind 完成。
我想让"Doing other things..." 保持异步打印。
【问题讨论】:
-
使用第二种方法,您可以收集
AddReminder返回的所有任务,然后使用await Task.WhenAll(tasks)等待它们全部完成。 -
您是否可以将 try catch 块放在您的
AddReminder方法中并使用 await 处理那里的事情,但在更高级别上不使用 await 以便您可以继续执行其他操作想要吗? -
是的。有可能,但是当 AddReminder 动作抛出异常时,仍然需要传播出去。