C# 如果不等待任务怎么办?
这是我的密码:C# 如果不等待任务怎么办?,c#,async-await,C#,Async Await,这是我的密码: private static Stopwatch _stopwatch; static void PrintException(Exception ex) { Console.WriteLine(_stopwatch.Elapsed); Console.WriteLine(ex); } static void ThrowException1() { throw new InvalidAsynchronousStateException(); } st
private static Stopwatch _stopwatch;
static void PrintException(Exception ex)
{
Console.WriteLine(_stopwatch.Elapsed);
Console.WriteLine(ex);
}
static void ThrowException1()
{
throw new InvalidAsynchronousStateException();
}
static void ThrowException2()
{
throw new NullReferenceException();
}
static async Task ExecuteTask1()
{
await Task.Delay(1000);
ThrowException1();
}
static async Task ExecuteTask2()
{
await Task.Delay(2000);
ThrowException2();
}
static async Task Execute()
{
var t1 = ExecuteTask1();
var t2 = ExecuteTask2();
try
{
await t2;
}
catch (NullReferenceException ex)
{
// the NullReferenceException will be captured
Console.WriteLine("==============");
PrintException(ex);
}
}
static void Main(string[] args)
{
TaskScheduler.UnobservedTaskException += (sender, ev) => PrintException(ev.Exception);
_stopwatch = Stopwatch.StartNew();
Execute();
while (true)
{
Thread.Sleep(5000);
GC.Collect();
}
}
实际上,我没有在Execute
方法中等待t1
,但它似乎仍然被执行,因为大约五秒钟后我捕获了aggregateeexception
有人能告诉我t1是什么时候执行的吗?在我的例子中,打印到控制台的异常顺序是1<代码>空引用异常2
aggregateeexception
如果您不等待它仍将执行的任务,那么您当前的执行上下文将不会“wati for it”
这意味着您无法直接控制任务,如果“任务内部”出现问题,异常将不会像使用Wait
或t1.Wait()时那样直接传播到您的执行上下文
在一般情况下,在任务中引发的异常被装箱在聚合异常中
,因此不能执行以下操作:
catch (NullReferenceException ex)
您需要执行以下操作并检查内部异常:
catch (AggregateException ex)
{
if(ex.InnerException is NullReferenceException)
// handle NRE
else
throw; // NOT "throw ex" to keep the stack trace
}
该任务是在此处调用ExecuteTask1的点执行的:
var t1 = ExecuteTask1();
您不需要等待任务执行,它无论如何都会运行。。。如果希望代码仅在任务完成后恢复执行,则等待任务,否则代码将在任务开始运行后立即继续运行,而不等待任务完成。在异步/等待世界中,任务是“热的”。因此,当您调用ExecuteTask1
时,返回给您的任务已经在处理中。这一点已经开始了。您可以在ExecuteTask*
的开头放置一个Console.WriteLine
,以查看它们是否立即启动
wait
仅用于(异步)等待任务完成。它不会启动任务
我在我的博客上有一个你可能会觉得有用的工具。注意:NullReferenceException
是一个保留的异常,因此不应该从用户代码中抛出它。@SriramSakthivel+1,我只是出于演示的目的使用它。谢谢你的回复,但在我的情况下,如果我只是用catch替换catch(NullReferenceException ex)
(AggregateException ex)
,将不会捕获异常。您还可以捕获泛型异常
,然后根据当前类型进行Deside…垃圾收集器是否也会跟踪此情况?假设您在类中执行此操作,则GC会因为认为没有更多引用而破坏属性吗?(如果您没有将任务返回/存储到任何位置)@JoelHarkes:在大多数情况下,任务不是GC'ed的,因为它们是由一个已传递给非托管代码的回调函数生成的。哈哈,谢谢“im most case”。好的,因此回调函数中使用的变量也不会被GC'ed。谢谢。@JoelHarkes:正确。任务
在完成之前唯一可以被GC'ed的情况是ldn仍然没有完成。(假设每个人的非托管调用都正确地固定了他们所需的内存)。