我有一个public async void Foo()方法,我想从同步方法调用.到目前为止,我从MSDN文档中看到的是通过异步方法调用异步方法,但我的整个程序不是使用异步方法构建的.
这甚至可能吗?
以下是从异步方法调用这些方法的一个示例:http://msdn.microsoft.com/en-us/library/hh300224(v = vs.110).aspx
现在我正在研究从同步方法调用这些异步方法.
前言:我正在寻找解释,而不仅仅是解决方案.我已经知道了解决方案.
尽管花了几天时间研究MSDN关于基于任务的异步模式(TAP),异步和等待的文章,但我仍然对一些更精细的细节感到困惑.
我正在为Windows Store应用程序编写一个记录器,我想支持异步和同步日志记录.异步方法遵循TAP,同步方法应该隐藏所有这些,并且看起来像普通方法一样工作.
这是异步日志记录的核心方法:
private async Task WriteToLogAsync(string text)
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync("log.log",
CreationCollisionOption.OpenIfExists);
await FileIO.AppendTextAsync(file, text,
Windows.Storage.Streams.UnicodeEncoding.Utf8);
}
Run Code Online (Sandbox Code Playgroud)
现在相应的同步方法......
版本1:
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Wait();
}
Run Code Online (Sandbox Code Playgroud)
这看起来是正确的,但它不起作用.整个程序永远冻结.
版本2:
嗯..也许任务没有开始?
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Start();
task.Wait();
}
Run Code Online (Sandbox Code Playgroud)
这引发了 InvalidOperationException: Start may not be called on a promise-style task.
版本3:
嗯.. Task.RunSynchronously听起来很有希望.
private void WriteToLog(string text)
{
Task task = …Run Code Online (Sandbox Code Playgroud) .net c# task-parallel-library async-await windows-store-apps
我正在更新具有在.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
我有一个返回任务的Async方法.
我也希望提供同步等效,但我不希望它的消费者必须去解包AggregateException.
现在我明白了整个想法是你不能随意选择一个,我知道我可以阅读更多的Stephen Toub文章(我会,但不是现在),我会理解这一切,并且可以自己决定.
在此期间,我想使用这样一个事实:我的任务实际上只是没有并行性的链接"工作流程",只是干预Waits(不,不是TPL DataFlow),这不应该导致多个异常.在这种情况下,处理如下是适当的:
CallAsync().Wait();
}
catch( AggregateException ae)
{
throw ae.Flatten().First()
Run Code Online (Sandbox Code Playgroud)
或者我保证即使有不止一个也AggregateException总是有InnerException.还是有一种情况我应该回归.Flatten().First()?
在一些TPL文档中,我看到了对Unwrap()方法的引用AggregateException(不确定它是否是扩展或beta版本中的某些内容).
作为占位符,我正在做:
void Call( )
{
try
{
CallAsync().Wait();
}
catch ( AggregateException ex )
{
var translated = ex.InnerException ?? ex.Flatten().InnerExceptions.First();
if ( translated == null )
throw;
throw translated; }
}
Task CallAsync(){ ...
Run Code Online (Sandbox Code Playgroud) asynchronous exception-handling task-parallel-library c#-4.0