在同步方法中运行没有 Wait() 的 Task.Run() 有啥影响?
Posted
技术标签:
【中文标题】在同步方法中运行没有 Wait() 的 Task.Run() 有啥影响?【英文标题】:What are the implications of running Task.Run() without Wait() in a synchronous method?在同步方法中运行没有 Wait() 的 Task.Run() 有什么影响? 【发布时间】:2021-06-21 18:55:51 【问题描述】:我有一个旧代码计时器,每 2 秒运行一次很长的数据库更新查询,类似这样
private void timer_Elapsed(object sender, ElapsedEventArgs e)
MySyncMethod();
private void MySyncMethod()
Task.Run(()=>Run a long running DB update query);
假设我们不需要数据库更新结果,上面代码中不等待任务完成有什么影响吗?
Task.Run(()=>Update something in DB).Wait();
据我了解,当我们调用 Task.Run() 时,会从线程池中获取一个新的/可用线程,并且该任务在该线程中运行。因为我们从 sync 方法调用 Task.Run(),所以我们不记得当前的同步上下文并在任务完成时恢复它,就像我们在 async 方法中使用 await Task.Run() 所做的那样。因此,我的另一个问题是,当任务完成时,后续命令是在任务线程中执行还是在原始线程中执行,即 MySyncMethod() 线程?例如,如果我的方法如下所示
private void MySyncMethod()
Task.Run(()=>Run a long running DB update query);
... Do something after Task is completed
是......做某事......在Task的线程中或Task完成后在MySyncMethod()线程中执行?
【问题讨论】:
如果您调用Task.Run(()=>Run a long running DB update query);
,您的数据库更新查询将被推送到Task
的队列中,并且当Task
有可用的Thread
并且它不会阻止您当前线。但是当你输入.Wait()
时,它会等到Task
有一个可用线程来完全运行你的查询,它会阻塞你当前的线程。请看:referencesource.microsoft.com/#mscorlib/system/threading/tasks/…
当我们从同步方法调用Task.Run()时,程序控制是否在Task.Run()调用后立即返回到被调用者的线程?任务完成后,程序控制是否留在任务线程中?当我们从同步方法调用 Task.Run() 时,我们没有像 async/await 方法那样的同步上下文恢复机制。这就是我的问题。
如果有人标记它以明确这里使用的是什么 PL(等),那就太好了。这看起来不是技术中立的......
如果查询的平均完成时间超过 2 秒,您认为会发生什么?你真的想发出比你的数据库服务器可以处理的更多的数据库请求吗?
好问题。我可能会重新编写此代码以制作异步计时器,即在数据库查询完成或超时之前不会执行下一个计时器迭代。购买它需要大量的代码更改。
【参考方案1】:
对不起,MBK,你有很多问题,所以我需要在这里回答:
1、当我们从同步方法调用Task.Run()时,程序控制是否在Task.Run()
调用后立即返回到被调用者的线程?
不,这取决于:
如果 Task 的队列中有 10 个线程和 0->9 个查询,那么您调用Task.Run(()=>query);
您的查询将立即运行
但如果 Task 在它的队列中有 10 个线程和 100 个查询,那么您调用 Task.Run(()=>query);
您的查询将不会立即运行,您的查询必须等待 91 个其他查询完全运行
2、任务完成后,程序控制是否停留在Task线程中?
我不知道你的意思,但如果你只是打电话给Task.Run(...)
,你无法知道你的查询是否可以在你的主线程上成功运行。
对于我来说,我只会使用Task.Run(...)
,我总是需要知道查询的结果,所以我会使用 Task.Run(...).Await() 或者如果我不想阻止主线程,我会结合一个回调来处理这样的查询结果:
Task.Run(()=>
try
//Run a long running DB update query
callback.onQueryRunSuccess();
catch(Exception e)
callback.onQueryRunFailed(e);
);
【讨论】:
我假设,您的意思是“我将使用 Task.Run(...).Wait()”,而不是“我将使用 Task.Run(...).Await()”以上是关于在同步方法中运行没有 Wait() 的 Task.Run() 有啥影响?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 .NET 中取消 Task.Wait() 之后正在运行的 OpenAsync()?