C# 捕获任务(task.Delay())执行的操作的异常
我构建了一种计划任务,它将在计划日期执行操作。我使用了C# 捕获任务(task.Delay())执行的操作的异常,c#,.net,C#,.net,我构建了一种计划任务,它将在计划日期执行操作。我使用了Task.Delay(Delay).ContinueWith(action.Invoke()) 有时操作会抛出异常,但仍然无法传播此异常以正确注册它 在我的示例中,a创建了一个包含三个文本的列表,空文本将抛出一个异常,但是我无法在try..catch块中捕获该异常 class Program { static async Task Main() { var texts = new
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
}
}
类程序
{
静态异步任务Main()
{
var text=new List(){“text 1”,null,“text 2”};
foreach(文本中的var文本)
{
var scheduleDate=DateTime.UtcNow.AddSeconds(10);
尝试
{
提醒控制。添加提醒(打印、文本、日程日期);
}
捕获(例外情况除外)
{
Console.WriteLine($“计划在{scheduleDate:s}.ex:{ex.Message}上打印文本{text}时出错);
}
}
while(true)
{
等待任务。延迟(2000);
Console.WriteLine(“做其他事情…”);
}
}
静态无效打印(对象文本)
{
如果(文本为空)
抛出新ArgumentNullException();\\抛出,但未传播出去
控制台写入线(文本);
}
}
公共类提醒控件
{
public static void addrementer(操作remiderCallback、对象上下文、DateTime scheduleDate)
{
var delay=scheduleDate.Subtract(DateTime.UtcNow);
任务。延迟(延迟)
.ContinueWith(t=>remiderCallback.Invoke(context));
//.ContinueWith(t=>throw t.Exception,TaskContinuationOptions.OnlyOnFaulted);即使使用此行,异常仍然不会传播
}
}
在任务中使用等待更新。延迟
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);
}
等待提醒控制。添加提醒(打印、文本、日程日期);
公共静态异步任务AddReminder(操作remiderCallback、对象上下文、DateTime scheduleDate)
{
var delay=scheduleDate.Subtract(DateTime.UtcNow);
等待任务。延迟(延迟);
调用(上下文);
}
在此之后,try..catch
块捕获了异常,但是,“正在做其他事情…”
停止打印,可能正在等待添加提醒
完成
我希望保持异步打印
“做其他事情…”
。如果希望异常从任务中正确出现,则需要使用完整的异步
编译器构造。将表达式替换为:
await Task.Delay(delay);
action.Invoke();
将它放入一个
async
函数中,该函数返回某种类型的任务
,并确保等待返回的任务。等待会让你抓到例外情况。谢谢。在任务中添加wait.Delay和wait后,我的主线程中的“正在做其他事情…”停止打印,可能是在等待addrementer。猜猜看?猜猜看,你的分析是正确的。如果您想询问如何使它仍然是异步的,同时保持try
。catch
围绕它,请将try
。catch
块和等待的addremememememplier
调用一个单独的async
函数,并在不等待的情况下调用该函数。是的,没错,我需要继续在外部异步工作。添加提醒类似于“开火并忘记”,但如果有任何问题,请记录下来。关于你的上一个建议,我对这两个建议有点困惑。try..catch
。所以我正在努力实现它。谢谢。我失败得很惨,我相信我不明白你的解决办法。你能用这个更新你的答案吗,或者看看我错在哪里@拉斐尔·皮门塔,试试这个:。总的来说,这不是一个好的解决方案,更好的解决方案包括一个依赖注入日志服务,该服务在未处理的异常情况下被调用,但此实现更符合您的项目。使用第二种方法,您可以收集由addrementer
返回的所有任务,然后使用wait Task等待它们全部完成。当所有(任务)
完成时,您是否可以将try-catch块放在addrementer
方法中,并使用wait在那里处理事情,但是在更高的层次上,不要使用wait,这样你就可以继续做你想做的其他事情了?是的。这是可能的,但是当AddRemembers操作抛出异常时,仍然需要将其传播出去。