我有一个public async void Foo()
方法,我想从同步方法调用.到目前为止,我从MSDN文档中看到的是通过异步方法调用异步方法,但我的整个程序不是使用异步方法构建的.
这甚至可能吗?
以下是从异步方法调用这些方法的一个示例:http://msdn.microsoft.com/en-us/library/hh300224(v = vs.110).aspx
现在我正在研究从同步方法调用这些异步方法.
我正在更新具有在.NET 3.5中构建的API表面的库.因此,所有方法都是同步的.我无法更改API(即,将返回值转换为Task),因为这将要求所有调用者都更改.所以我留下了如何以同步方式最好地调用异步方法.这是在ASP.NET 4,ASP.NET Core和.NET/.NET Core控制台应用程序的上下文中.
我可能不够清楚 - 情况是我现有的代码不是异步识别的,我想使用新的库,如System.Net.Http和仅支持异步方法的AWS SDK.所以我需要缩小差距,并且能够拥有可以同步调用的代码,然后可以在其他地方调用异步方法.
我已经做了很多阅读,并且有很多次这已经被问及并回答了.
问题是大多数答案都不同!我见过的最常见的方法是使用.Result,但这可能会死锁.我已经尝试了以下所有内容,并且它们可以工作,但我不确定哪种方法可以避免死锁,具有良好的性能,并且可以很好地运行运行时(在尊重任务调度程序,任务创建选项等方面) ).有明确的答案吗?什么是最好的方法?
private static T taskSyncRunner<T>(Func<Task<T>> task)
{
T result;
// approach 1
result = Task.Run(async () => await task()).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 2
result = Task.Run(task).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 3
result = task().ConfigureAwait(false).GetAwaiter().GetResult();
// approach 4
result = Task.Run(task).Result;
// approach 5
result = Task.Run(task).GetAwaiter().GetResult();
// approach 6
var t = task();
t.RunSynchronously();
result = t.Result;
// approach 7
var t1 = task();
Task.WaitAll(t1); …
Run Code Online (Sandbox Code Playgroud) c# asp.net multithreading asynchronous task-parallel-library
我有以下代码:
static async Task Callee()
{
await Task.Delay(1000);
}
static async Task Caller()
{
Callee(); // #1 fire and forget
await Callee(); // #2 >1s
Task.Run(() => Callee()); // #3 fire and forget
await Task.Run(() => Callee()); // #4 >1s
Task.Run(async () => await Callee()); // #5 fire and forget
await Task.Run(async () => await Callee()); // #6 >1s
}
static void Main(string[] args)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
Caller().Wait();
stopWatch.Stop();
Console.WriteLine($"Elapsed: {stopWatch.ElapsedMilliseconds}");
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
#1以最简单的方式点火和忘记.#2只是等待.有趣的东西从#3开始.这些电话背后的深度逻辑是什么?
我知道在ASP.NET中使用fire'n'forget作为警告的指向这里 …