如果我在C#中的RunSynchronously()
上调用Task
,这是否会导致同步进行兔子洞的异步调用?
假设我有一个名为UpdateAsync()
的方法。在此方法中,对DoSomethingAsync()
进行了另一次异步调用,在此内部我们再次找到DoSomethingElseAsync()
,将在'UpdateAsync()'上调用RunSynchronously()
导致RunSynchronously()
也被间接调用在DoSomethingAsync()
?
我的问题原因:
我有一种情况,我需要在UpdateAsync()
- 块内调用异步方法(catch
),并想知道用RunSynchronously()
调用它是否安全。文档非常清楚,你不能在await
- 块内catch
。 (严格来说,我可以在catch
- 块中使用布尔值,并在try-catch之后调用UpdateAsync()
,但这感觉相当脏。对于双重问题感到抱歉,但是您可能已经理解我不太清楚如何用它来表达它并且对这个领域没有很好的理解。
(修改 我不知道如何查明方法是否异步调用。你会如何为此编写单元测试?有可能以某种方式记录它吗?)
答案 0 :(得分:6)
我“需要”调用一个异步方法,并想知道用
RunSynchronously()
调用它是否安全
Task
有两种:基于代码* Tasks
(您可以使用Task
构造函数或Task.Factory.StartNew()
创建这些内容)和promise-style { {1}}(您可以使用Task
或通过编写TaskCompletionSource
方法手动创建它们。)
您可以通过调用async
或Task
开始的唯一Start()
是未启动的基于代码的RunSynchronously()
s 。由于异步方法返回promise-style Task
(或者可能已经启动的基于代码的Task
),因此对它们调用Task
无效并将导致异常。
所以,要真正回答你的问题:你所要求的是不可能的,所以询问它是否安全是没有意义的。
*这不是正式名称,我不知道是否有正式名称。
答案 1 :(得分:0)
如果没有代码,很难预测它将如何执行嵌套的异步方法。
您可以登录每个异步方法Thread.CurrentThread.ManagedThreadId属性,并将id与您拥有的其他线程ID进行比较。当它们变化时,您的异步方法处于多线程执行
或尝试使用Visual Studio,Analyze菜单中的Concurrency Visualizer。使用Task类实例,甚至使用C#5异步语法,无法知道您是在并行执行还是在另一个线程中执行。
答案 2 :(得分:-1)
我想我会反驳@svick的答案,但我觉得OP问题是有效的,因为异步方法的“承诺”(使用Svick的术语)任务可以获得,但不能启动,因此允许{ {1}}。
Task.RunSynchronously()
话虽如此,答案是:不, static void Main(string[] args)
{
...
//obtain a Task that's not started
var t = new Task<int>((ob) => GetIntAsync((string)ob).Result, someString);
...
}
static async Task<int> GetIntAsync(string callerThreadId)
{
...
会影响您运行此任务的任务。如果调用链稍后包含更多异步调用,则它们将异步运行。
我有一个小的控制台应用程序正在对此进行建模,有人有兴趣看到它,但这个概念很容易重现 - 只需链接足够的异步调用并在同步和异步运行最早的一个之间切换以查看不同的行为。