将同步方法包装为异步:无需等待结果重复执行的疑问
嘿,我来帮你把这个问题理清楚~
首先纠正一个关键误解:“如果不使用await获取结果,任务将无法继续执行”这个说法是错误的。当你用Task.Run(() => Exec())启动任务时,这个任务会立刻被放到线程池里开始执行,不管你有没有用await等待它,它都会在后台线程跑起来。await的作用只是让当前的线程暂停,等待任务完成后再继续往下走,完全不影响任务本身的执行。
针对你的需求——无需等待前一个任务完成、不关心执行结果,只需要重复启动任务——给你几个关键点:
去掉不必要的await:你的示例代码里的
await task其实是画蛇添足,它会让MakeRequest方法等待任务执行完才启动mainTimer,反而变成了串行执行,不符合你的需求。改成下面这样就可以:private void MakeRequest() { mainTimer.Stop(); // 直接启动后台任务,不用等待它完成 Task.Run(() => Exec()); mainTimer.Start(); }这样每次调用
MakeRequest时,会立刻启动一个新的后台任务,当前线程不用等待任务结束,马上就会重启定时器,完全满足你“无需等待前一个任务”的要求。注意异常处理:因为你不关心任务结果,后台任务如果抛出异常,在老版本的.NET里可能会导致进程崩溃(.NET Core及以后版本会自动吞掉未观察到的任务异常,但还是建议处理)。所以最好在
Exec()方法内部加上异常捕获:private void Exec() { try { // 你的业务逻辑:读取未处理记录、执行业务操作 } catch (Exception ex) { // 这里可以记录日志,或者做其他异常处理 // 比如 Logger.Error("处理任务出错", ex); } }资源占用问题:如果短时间内多次触发任务,可能会创建大量线程池线程,导致资源紧张。不过根据你的场景——通常无记录可处理,处理时长波动但触发频率不高——这个问题应该不会太严重。如果后续出现频繁触发的情况,可以考虑用任务队列或者限制并发数,但目前来看不需要额外处理。
总结一下:你完全不需要用await来让任务执行,直接调用Task.Run就能启动后台任务,而且不用等待它完成,定时器可以立刻重启,实现你想要的“不管前一个任务是否完成,都再次启动任务”的效果。
内容的提问来源于stack exchange,提问作者Frank Cedeno

