Unit Test for number of threads created by threading code - c#

I have a threading module in my app which manages initiating parallel operations. It adds various bits of timing and logging for reasons, and is complicated enough that I recently discovered I'd coded in a bug whereby it was initiating some of the tasks on doubly nested threads.
i.e. it was calling the equivalent of:
Task.Run(
async () => await Task.Run(
() => DoStuff();
);
).Wait()
Now on the one hand, that code works ... the target code gets run, and the waiting code doesn't continue until the target code has completed.
On the other hand, it's using 2 threads to do this rather than 1 and since we're having issues with thread-starvation, that's something of an issue.
I know how to fix the code, but I'd like to write a unit test to ensure that A) I've fixed all the bugs like this / fixed it in all the scenarios.
and B) no-one recreates this bug in the future.
But I can't see how to get hold of "all the threads that I've created". CurrentProcess.Threads gives me LOADS of threads, and no obvious way to identify which ones are the ones I care about.
Any thoughts?

As is often the solution with unit testing something that involves a static method (Task.Run in this case), you will likely need to pass something in as a dependency to your class that wraps this up and that you can then add behaviour to in the tests.
As #Rich suggests in his answer, you could do this by passing in a TaskScheduler. Your test version of this can then maintain a count of the tasks as they are enqueued.
Making a test TaskScheduler is actually a little ugly because of protection levels, but at the bottom of this post I have included one that wraps an existing TaskScheduler (e.g. you could use TaskScheduler.Default).
Unfortunately, you would also need to change your calls like
Task.Run(() => DoSomething);
to something like
Task.Factory.StartNew(
() => DoSomething(),
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
myTaskScheduler);
which is basically what Task.Run does under the hood, except with the TaskScheduler.Default. You could of course wrap that up in a helper method somewhere.
Alternatively, if you are not squeamish about some riskier reflection in your test code you could hijack the TaskScheduler.Default property, so that you can still just use Task.Run:
var defaultSchedulerField = typeof(TaskScheduler).GetField("s_defaultTaskScheduler", BindingFlags.Static | BindingFlags.NonPublic);
var scheduler = new TestTaskScheduler(TaskScheduler.Default);
defaultSchedulerField.SetValue(null, scheduler);
(Private field name is from TaskScheduler.cs line 285.)
So for example, this test would pass using my TestTaskScheduler below and the reflection trick:
[Test]
public void Can_count_tasks()
{
// Given
var originalScheduler = TaskScheduler.Default;
var defaultSchedulerField = typeof(TaskScheduler).GetField("s_defaultTaskScheduler", BindingFlags.Static | BindingFlags.NonPublic);
var testScheduler = new TestTaskScheduler(originalScheduler);
defaultSchedulerField.SetValue(null, testScheduler);
// When
Task.Run(() => {});
Task.Run(() => {});
Task.Run(() => {});
// Then
testScheduler.TaskCount.Should().Be(3);
// Clean up
defaultSchedulerField.SetValue(null, originalScheduler);
}
Here is the test task scheduler:
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
public class TestTaskScheduler : TaskScheduler
{
private static readonly MethodInfo queueTask = GetProtectedMethodInfo("QueueTask");
private static readonly MethodInfo tryExecuteTaskInline = GetProtectedMethodInfo("TryExecuteTaskInline");
private static readonly MethodInfo getScheduledTasks = GetProtectedMethodInfo("GetScheduledTasks");
private readonly TaskScheduler taskScheduler;
public TestTaskScheduler(TaskScheduler taskScheduler)
{
this.taskScheduler = taskScheduler;
}
public int TaskCount { get; private set; }
protected override void QueueTask(Task task)
{
TaskCount++;
CallProtectedMethod(queueTask, task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return (bool)CallProtectedMethod(tryExecuteTaskInline, task, taskWasPreviouslyQueued);
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return (IEnumerable<Task>)CallProtectedMethod(getScheduledTasks);
}
private object CallProtectedMethod(MethodInfo methodInfo, params object[] args)
{
return methodInfo.Invoke(taskScheduler, args);
}
private static MethodInfo GetProtectedMethodInfo(string methodName)
{
return typeof(TaskScheduler).GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
}
}
or tidied up using RelflectionMagic as suggested by #hgcummings in the comments:
var scheduler = new TestTaskScheduler(TaskScheduler.Default);
typeof(TaskScheduler).AsDynamicType().s_defaultTaskScheduler = scheduler;
using System.Collections.Generic;
using System.Threading.Tasks;
using ReflectionMagic;
public class TestTaskScheduler : TaskScheduler
{
private readonly dynamic taskScheduler;
public TestTaskScheduler(TaskScheduler taskScheduler)
{
this.taskScheduler = taskScheduler.AsDynamic();
}
public int TaskCount { get; private set; }
protected override void QueueTask(Task task)
{
TaskCount++;
taskScheduler.QueueTask(task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return taskScheduler.TryExecuteTaskInline(task, taskWasPreviouslyQueued);
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return taskScheduler.GetScheduledTasks();
}
}

how to get hold of "all the threads that I've created"
Task.Run does not create any threads; it schedules jobs to run on the currently configured thread pool. See https://msdn.microsoft.com/library/system.threading.tasks.taskscheduler.aspx
If you mean "how to count the number of Tasks I've enqueued", I think you will need to create a custom implementation of TaskScheduler which counts incoming tasks and configure your test code to use it. There is an example of a custom TaskScheduler shown on the page linked above.

The thread class does have a Name property you could use to help identify all the threads you have created. Meaning a simple linq or for loop that will enable you to track which threads are yours.
https://msdn.microsoft.com/en-us/library/system.threading.thread.name(v=vs.110).aspx

Related

Why is my custom current scheduler replaced by the default one when I use ConfigureAwait(false)?

I wrote a custom TaskScheduler which is supposed to execute given tasks on the same thread. This task scheduler is used with a custom task factory. This task factory executes an async method ReadFileAsync which calls another async method ReadToEndAsync of StreamReader.
I've noticed that after using ReadToEndAsync().ConfigureAwait(false), the current task scheduler is reverted back to the default one, ThreadPoolTaskScheduler. If I remove ConfigureAwait(false), the custom task scheduler SameThreadTaskScheduler is kept. Why? Is there any way to use ConfigureAwait(false) with the same custom scheduler after its execution?
I've tried multiple things, but the result is the same:
Change the enum flags of the custom TaskFactory
Using a custom synchronization context that Posts the callback synchronously instead of the thread pool
Change and revert the synchronization inside the task function executed on the task factory
Change and revert the synchronization outside of the task function executed on the task factory
public static class Program
{
private static readonly string DesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
public static void Main()
{
_ = AsyncHelper.RunSynchronously(ReadFileAsync);
}
private static async Task<string> ReadFileAsync()
{
// Prints "SameThreadTaskScheduler"
Console.WriteLine(TaskScheduler.Current.GetType().Name);
using var fs = File.OpenText(Path.Combine(DesktopPath, "hello.txt"));
var content = await fs.ReadToEndAsync().ConfigureAwait(false); // <-------- HERE
// With ReadToEndAsync().ConfigureAwait(false), prints "ThreadPoolTaskScheduler"
// With ReadToEndAsync() only, prints "SameThreadTaskScheduler"
Console.WriteLine(TaskScheduler.Current.GetType().Name);
return content;
}
}
public static class AsyncHelper
{
private static readonly TaskFactory SameThreadTaskFactory = new TaskFactory(
CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
new SameThreadTaskScheduler());
public static TResult RunSynchronously<TResult>(Func<Task<TResult>> func)
{
var oldContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
return SameThreadTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
}
finally
{
SynchronizationContext.SetSynchronizationContext(oldContext);
}
}
}
public sealed class SameThreadTaskScheduler : TaskScheduler
{
public override int MaximumConcurrencyLevel => 1;
protected override void QueueTask(Task task)
{
this.TryExecuteTask(task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
this.TryExecuteTask(task);
return true;
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return Enumerable.Empty<Task>();
}
}
The parameter continueOnCapturedContext in ConfigureAwait(bool continueOnCapturedContext) has the following meaning: If true is specified, this means that the continuation should be marshaled back to the original context captured. If false is specified, the continuation may run on an arbitrary context.
The synchronization context is an abstraction for scheduling. A TaskScheduler is a concrete implementation. So by specifying ConfigureAwait(false), you state that any TaskScheduler can be used. If you want to use your special TaskScheduler, than use ConfigureAwait(true).
For more information on this topic, take a look at this post.

Await for a task inside an async method [duplicate]

I have a public async void Foo() method that I want to call from synchronous method. So far all I have seen from MSDN documentation is calling async methods via async methods, but my whole program is not built with async methods.
Is this even possible?
Here's one example of calling these methods from an asynchronous method:
Walkthrough: Accessing the Web by Using Async and Await (C# and Visual Basic)
Now I'm looking into calling these async methods from sync methods.
Asynchronous programming does "grow" through the code base. It has been compared to a zombie virus. The best solution is to allow it to grow, but sometimes that's not possible.
I have written a few types in my Nito.AsyncEx library for dealing with a partially-asynchronous code base. There's no solution that works in every situation, though.
Solution A
If you have a simple asynchronous method that doesn't need to synchronize back to its context, then you can use Task.WaitAndUnwrapException:
var task = MyAsyncMethod();
var result = task.WaitAndUnwrapException();
You do not want to use Task.Wait or Task.Result because they wrap exceptions in AggregateException.
This solution is only appropriate if MyAsyncMethod does not synchronize back to its context. In other words, every await in MyAsyncMethod should end with ConfigureAwait(false). This means it can't update any UI elements or access the ASP.NET request context.
Solution B
If MyAsyncMethod does need to synchronize back to its context, then you may be able to use AsyncContext.RunTask to provide a nested context:
var result = AsyncContext.RunTask(MyAsyncMethod).Result;
*Update 4/14/2014: In more recent versions of the library the API is as follows:
var result = AsyncContext.Run(MyAsyncMethod);
(It's OK to use Task.Result in this example because RunTask will propagate Task exceptions).
The reason you may need AsyncContext.RunTask instead of Task.WaitAndUnwrapException is because of a rather subtle deadlock possibility that happens on WinForms/WPF/SL/ASP.NET:
A synchronous method calls an async method, obtaining a Task.
The synchronous method does a blocking wait on the Task.
The async method uses await without ConfigureAwait.
The Task cannot complete in this situation because it only completes when the async method is finished; the async method cannot complete because it is attempting to schedule its continuation to the SynchronizationContext, and WinForms/WPF/SL/ASP.NET will not allow the continuation to run because the synchronous method is already running in that context.
This is one reason why it's a good idea to use ConfigureAwait(false) within every async method as much as possible.
Solution C
AsyncContext.RunTask won't work in every scenario. For example, if the async method awaits something that requires a UI event to complete, then you'll deadlock even with the nested context. In that case, you could start the async method on the thread pool:
var task = Task.Run(async () => await MyAsyncMethod());
var result = task.WaitAndUnwrapException();
However, this solution requires a MyAsyncMethod that will work in the thread pool context. So it can't update UI elements or access the ASP.NET request context. And in that case, you may as well add ConfigureAwait(false) to its await statements, and use solution A.
Update, 2019-05-01: The current "least-worst practices" are in an MSDN article here.
Adding a solution that finally solved my problem, hopefully saves somebody's time.
Firstly read a couple articles of Stephen Cleary:
Async and Await
Don't Block on Async Code
From the "two best practices" in "Don't Block on Async Code", the first one didn't work for me and the second one wasn't applicable (basically if I can use await, I do!).
So here is my workaround: wrap the call inside a Task.Run<>(async () => await FunctionAsync()); and hopefully no deadlock anymore.
Here is my code:
public class LogReader
{
ILogger _logger;
public LogReader(ILogger logger)
{
_logger = logger;
}
public LogEntity GetLog()
{
Task<LogEntity> task = Task.Run<LogEntity>(async () => await GetLogAsync());
return task.Result;
}
public async Task<LogEntity> GetLogAsync()
{
var result = await _logger.GetAsync();
// more code here...
return result as LogEntity;
}
}
Microsoft built an AsyncHelper (internal) class to run Async as Sync. The source looks like:
internal static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return AsyncHelper._myTaskFactory
.StartNew<Task<TResult>>(func)
.Unwrap<TResult>()
.GetAwaiter()
.GetResult();
}
public static void RunSync(Func<Task> func)
{
AsyncHelper._myTaskFactory
.StartNew<Task>(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
The Microsoft.AspNet.Identity base classes only have Async methods and in order to call them as Sync there are classes with extension methods that look like (example usage):
public static TUser FindById<TUser, TKey>(this UserManager<TUser, TKey> manager, TKey userId) where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
return AsyncHelper.RunSync<TUser>(() => manager.FindByIdAsync(userId));
}
public static bool IsInRole<TUser, TKey>(this UserManager<TUser, TKey> manager, TKey userId, string role) where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
return AsyncHelper.RunSync<bool>(() => manager.IsInRoleAsync(userId, role));
}
For those concerned about the licensing terms of code, here is a link to very similar code (just adds support for culture on the thread) that has comments to indicate that it is MIT Licensed by Microsoft. https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Core/AsyncHelper.cs
Wouldn't this be the same as just calling Task.Run(async ()=> await AsyncFunc()).Result? AFAIK, Microsoft is now discouraging from calling TaskFactory.StartNew, since they are both equivalent and one is more readable than the other.
Absolutely not.
The easy answer is that
.Unwrap().GetAwaiter().GetResult() != .Result
First off the
Is Task.Result the same as .GetAwaiter.GetResult()?
Secondly .Unwrap() causes the setup of the Task not to block the wrapped task.
Which should lead anyone to ask
Wouldn't this be the same as just calling Task.Run(async ()=> await AsyncFunc()).GetAwaiter().GetResult()
Which would then be a It Depends.
Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew()
Excerpt:
Task.Run uses TaskCreationOptions.DenyChildAttach which means that children's tasks can not be attached to the parent and it uses TaskScheduler.Default which means that the one that runs tasks on Thread Pool will always be used to run tasks.
Task.Factory.StartNew uses TaskScheduler.Current which means scheduler of the current thread, it might be TaskScheduler.Default but not always.
Additional Reading:
Specifying a synchronization context
ASP.NET Core SynchronizationContext
For extra safety, wouldn't it be better to call it like this AsyncHelper.RunSync(async () => await AsyncMethod().ConfigureAwait(false)); This way we're telling the "inner" method "please don't try to sync to upper context and dealock"
Really great point and as most object architectural questions go it depends.
As an extension method do you want to force that for absolutely every call, or do you let the programmer using the function configure that on their own async calls? I could see a use case for call three scenarios; it most likely is not something you want in WPF, certainly makes sense in most cases, but considering there is no Context in ASP.Net Core if you could guarantee it was say internal for a ASP.Net Core, then it wouldn't matter.
async Main is now part of C# 7.2 and can be enabled in the projects advanced build settings.
For C# < 7.2, the correct way is:
static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
/*await stuff here*/
}
You'll see this used in a lot of Microsoft documentation, for example:
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions
I'm not 100% sure, but I believe the technique described in this blog should work in many circumstances:
You can thus use task.GetAwaiter().GetResult() if you want to directly invoke this propagation logic.
public async Task<string> StartMyTask()
{
await Foo()
// code to execute once foo is done
}
static void Main()
{
var myTask = StartMyTask(); // call your method which will return control once it hits await
// now you can continue executing code here
string result = myTask.Result; // wait for the task to complete to continue
// use result
}
You read the 'await' keyword as "start this long running task, then return control to the calling method". Once the long-running task is done, then it executes the code after it. The code after the await is similar to what used to be CallBack methods. The big difference being the logical flow is not interrupted which makes it much easier to write and read.
There is, however, a good solution that works in (almost: see comments) every situation: an ad-hoc message pump (SynchronizationContext).
The calling thread will be blocked as expected, while still ensuring that all continuations called from the async function don't deadlock as they'll be marshaled to the ad-hoc SynchronizationContext (message pump) running on the calling thread.
The code of the ad-hoc message pump helper:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Threading
{
/// <summary>Provides a pump that supports running asynchronous methods on the current thread.</summary>
public static class AsyncPump
{
/// <summary>Runs the specified asynchronous method.</summary>
/// <param name="asyncMethod">The asynchronous method to execute.</param>
public static void Run(Action asyncMethod)
{
if (asyncMethod == null) throw new ArgumentNullException("asyncMethod");
var prevCtx = SynchronizationContext.Current;
try
{
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(true);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function
syncCtx.OperationStarted();
asyncMethod();
syncCtx.OperationCompleted();
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
}
finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
}
/// <summary>Runs the specified asynchronous method.</summary>
/// <param name="asyncMethod">The asynchronous method to execute.</param>
public static void Run(Func<Task> asyncMethod)
{
if (asyncMethod == null) throw new ArgumentNullException("asyncMethod");
var prevCtx = SynchronizationContext.Current;
try
{
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(false);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function and alert the context to when it completes
var t = asyncMethod();
if (t == null) throw new InvalidOperationException("No task provided.");
t.ContinueWith(delegate { syncCtx.Complete(); }, TaskScheduler.Default);
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
t.GetAwaiter().GetResult();
}
finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
}
/// <summary>Runs the specified asynchronous method.</summary>
/// <param name="asyncMethod">The asynchronous method to execute.</param>
public static T Run<T>(Func<Task<T>> asyncMethod)
{
if (asyncMethod == null) throw new ArgumentNullException("asyncMethod");
var prevCtx = SynchronizationContext.Current;
try
{
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(false);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function and alert the context to when it completes
var t = asyncMethod();
if (t == null) throw new InvalidOperationException("No task provided.");
t.ContinueWith(delegate { syncCtx.Complete(); }, TaskScheduler.Default);
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
return t.GetAwaiter().GetResult();
}
finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
}
/// <summary>Provides a SynchronizationContext that's single-threaded.</summary>
private sealed class SingleThreadSynchronizationContext : SynchronizationContext
{
/// <summary>The queue of work items.</summary>
private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> m_queue =
new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
/// <summary>The processing thread.</summary>
private readonly Thread m_thread = Thread.CurrentThread;
/// <summary>The number of outstanding operations.</summary>
private int m_operationCount = 0;
/// <summary>Whether to track operations m_operationCount.</summary>
private readonly bool m_trackOperations;
/// <summary>Initializes the context.</summary>
/// <param name="trackOperations">Whether to track operation count.</param>
internal SingleThreadSynchronizationContext(bool trackOperations)
{
m_trackOperations = trackOperations;
}
/// <summary>Dispatches an asynchronous message to the synchronization context.</summary>
/// <param name="d">The System.Threading.SendOrPostCallback delegate to call.</param>
/// <param name="state">The object passed to the delegate.</param>
public override void Post(SendOrPostCallback d, object state)
{
if (d == null) throw new ArgumentNullException("d");
m_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
}
/// <summary>Not supported.</summary>
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("Synchronously sending is not supported.");
}
/// <summary>Runs an loop to process all queued work items.</summary>
public void RunOnCurrentThread()
{
foreach (var workItem in m_queue.GetConsumingEnumerable())
workItem.Key(workItem.Value);
}
/// <summary>Notifies the context that no more work will arrive.</summary>
public void Complete() { m_queue.CompleteAdding(); }
/// <summary>Invoked when an async operation is started.</summary>
public override void OperationStarted()
{
if (m_trackOperations)
Interlocked.Increment(ref m_operationCount);
}
/// <summary>Invoked when an async operation is completed.</summary>
public override void OperationCompleted()
{
if (m_trackOperations &&
Interlocked.Decrement(ref m_operationCount) == 0)
Complete();
}
}
}
}
Usage:
AsyncPump.Run(() => FooAsync(...));
More detailed description of the async pump is available here.
To anyone paying attention to this question anymore...
If you look in Microsoft.VisualStudio.Services.WebApi there's a class called TaskExtensions. Within that class you'll see the static extension method Task.SyncResult(), which like totally just blocks the thread till the task returns.
Internally it calls task.GetAwaiter().GetResult() which is pretty simple, however it's overloaded to work on any async method that return Task, Task<T> or Task<HttpResponseMessage>... syntactic sugar, baby... daddy's got a sweet tooth.
It looks like ...GetAwaiter().GetResult() is the MS-official way to execute async code in a blocking context. Seems to work very fine for my use case.
var result = Task.Run(async () => await configManager.GetConfigurationAsync()).ConfigureAwait(false);
OpenIdConnectConfiguration config = result.GetAwaiter().GetResult();
Or use this:
var result=result.GetAwaiter().GetResult().AccessToken
You can call any asynchronous method from synchronous code, that is, until you need to await on them, in which case they have to be marked as async too.
As a lot of people are suggesting here, you could call Wait() or Result on the resulting task in your synchronous method, but then you end up with a blocking call in that method, which sort of defeats the purpose of async.
If you really can't make your method async and you don't want to lock up the synchronous method, then you're going to have to use a callback method by passing it as parameter to the ContinueWith() method on task.
Inspired by some of the other answers, I created the following simple helper methods:
public static TResult RunSync<TResult>(Func<Task<TResult>> method)
{
var task = method();
return task.GetAwaiter().GetResult();
}
public static void RunSync(Func<Task> method)
{
var task = method();
task.GetAwaiter().GetResult();
}
They can be called as follows (depending on whether you are returning a value or not):
RunSync(() => Foo());
var result = RunSync(() => FooWithResult());
Note that the signature in the original question public async void Foo() is incorrect. It should be public async Task Foo() as you should return Task not void for async methods that don't return a value (yes, there are some rare exceptions).
Stephen Cleary's Answer;
That approach shouldn't cause a deadlock (assuming that
ProblemMethodAsync doesn't send updates to the UI thread or anything
like that). It does assume that ProblemMethodAsync can be called on a
thread pool thread, which is not always the case.
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
And here is the approach;
The Thread Pool Hack A similar approach to the Blocking Hack is to
offload the asynchronous work to the thread pool, then block on the
resulting task. The code using this hack would look like the code
shown in Figure 7.
Figure 7 Code for the Thread Pool Hack
C#
public sealed class WebDataService : IDataService
{
public string Get(int id)
{
return Task.Run(() => GetAsync(id)).GetAwaiter().GetResult();
}
public async Task<string> GetAsync(int id)
{
using (var client = new WebClient())
return await client.DownloadStringTaskAsync(
"https://www.example.com/api/values/" + id);
}
}
The call to Task.Run executes the asynchronous method on a thread pool
thread. Here it will run without a context, thus avoiding the
deadlock. One of the problems with this approach is the asynchronous
method can’t depend on executing within a specific context. So, it
can’t use UI elements or the ASP.NET HttpContext.Current.
Here is the simplest solution. I saw it somewhere on the Internet, I didn't remember where, but I have been using it successfully. It will not deadlock the calling thread.
void SynchronousFunction()
{
Task.Run(Foo).Wait();
}
string SynchronousFunctionReturnsString()
{
return Task.Run(Foo).Result;
}
string SynchronousFunctionReturnsStringWithParam(int id)
{
return Task.Run(() => Foo(id)).Result;
}
After hours of trying different methods, with more or less success, this is what I ended with. It doesn't end in a deadlock while getting result and it also gets and throws the original exception and not the wrapped one.
private ReturnType RunSync()
{
var task = Task.Run(async () => await myMethodAsync(agency));
if (task.IsFaulted && task.Exception != null)
{
throw task.Exception;
}
return task.Result;
}
You can now use source generators to create a sync version of your method using Sync Method Generator library (nuget).
Use it as follows:
[Zomp.SyncMethodGenerator.CreateSyncVersion]
public async void FooAsync()
Which will generate Foo method which you can call synchronously.
Those windows async methods have a nifty little method called AsTask(). You can use this to have the method return itself as a task so that you can manually call Wait() on it.
For example, on a Windows Phone 8 Silverlight application, you can do the following:
private void DeleteSynchronous(string path)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Task t = localFolder.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask();
t.Wait();
}
private void FunctionThatNeedsToBeSynchronous()
{
// Do some work here
// ....
// Delete something in storage synchronously
DeleteSynchronous("pathGoesHere");
// Do other work here
// .....
}
Hope this helps!
If you want to run it Sync
MethodAsync().RunSynchronously()

How to use sequence when testing async methods?

I am using Moq.Sequences and I am having trouble with testing async methods.
When I do this:
[Test]
public async Task Demo()
{
using (Sequence.Create())
{
_fooMock.Setup(f => f.Fooxiate()).InSequence();
_barMock.Setup(b => b.Baronize()).InSequence();
var result = await _cut.DoMyStuffAsync();
Assert.AreEqual("someString", result);
}
}
The I get an exception in the production code when calling _foo.Fooxiate() saying:
Moq.Sequences.SequenceUsageException: 'Mock invocation can only be called with an active MockSequence created with MockSequence.Create()
Am I doing something wrong or is testing of call sequence in async methods not supported?
Here is the full demo code including the above mentioned production code:
using System.Threading.Tasks;
using Moq;
using Moq.Sequences;
using NUnit.Framework;
namespace TestingAsync.Tests
{
[TestFixture]
public class SomeClassTests
{
private SomeClass _cut;
private Mock<IFoo> _fooMock;
private Mock<IBar> _barMock;
[SetUp]
public void Setup()
{
_fooMock = new Mock<IFoo>();
_barMock = new Mock<IBar>();
_cut = new SomeClass(_fooMock.Object, _barMock.Object);
}
[Test]
public async Task Demo()
{
using (Sequence.Create())
{
_fooMock.Setup(f => f.Fooxiate()).InSequence();
_barMock.Setup(b => b.Baronize()).InSequence();
var result = await _cut.DoMyStuffAsync();
Assert.AreEqual("someString", result);
}
}
}
public class SomeClass
{
private readonly IFoo _foo;
private readonly IBar _bar;
public SomeClass(IFoo foo, IBar bar)
{
_bar = bar;
_foo = foo;
}
public async Task<string> DoMyStuffAsync()
{
return await Task.Run(() => DoMyStuff());
}
private string DoMyStuff()
{
_foo.Fooxiate();
_bar.Baronize();
return "someString";
}
}
public interface IBar
{
void Baronize();
}
public interface IFoo
{
void Fooxiate();
}
}
This other answer explains correctly how Moq.Sequences doesn't didn't properly support async / await due to its use of [ThreadStatic].
Based on the OP's request, I've updated that library to provide better support for modern concurrent programming patterns. (Hopefully, people are programming with Tasks these days, not Threads.)
Starting with version 2.1.0, you can make Moq.Sequences track the ambient sequence using a AsyncLocal<Sequence> instead of a [ThreadStatic] variable. This means that the ambient sequence can "flow" across async boundaries such as an await and still be visible in the continuation (which might run on a different thread).
For reasons of backwards compatibility, you currently need to opt in to the new behavior by doing the following before any of your tests run:
Sequence.ContextMode = SequenceContextMode.Async;
At this time of writing, the new behavior hasn't been extensively tested so issue and bug reports are welcome.
Moq.Sequences is not written to be multi-threaded as it uses the [ThreadStatic] attribute to keep track of the ambient Sequence.
[ThreadStatic]
private static Sequence instance;
The result is that the ambient Sequence is only stored for the current thread. Then you call Task.Run which spawns a background thread to do work. This results in the exception being thrown because instance is null for that thread.
if (Instance == null)
throw new SequenceUsageException(context + " can only be called with an active MockSequence created with MockSequence.Create()");
https://github.com/dwhelan/Moq-Sequences → src/Moq.Sequences/Sequence.cs
There is not a good way for Moq.Sequences to be able to guarantee order of calls in async code because:
Concurrent code does not typically have deterministic order of execution.
Async is an abstraction over threads and because of that is even less predictable than threads. There are many techniques that result in non-deterministic sequence of calls, such as doing work in background threads with Task.Run, using Parallel.For/ForEach, using TPL dataflow, using Task.WhenAll, etc.

Using Task.Run() for hardware interfacing thread invocations

I need to invoke a method that meets the following criteria.
The method may run for hours.
The method may interface with hardware.
The method may request user input (parameter values, confirmation, etc). The request should block the method until input has been received.
I have a prototype implementation that fulfills this criteria using the following design.
Assume a Form exists and contains a Panel.
The IntegerInput class is a UserControl with a TextBox and a Button.
public partial class IntegerInput : UserControl
{
public TaskCompletionSource<int> InputVal = new TaskCompletionSource<int>(0);
public IntegerInput()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int val = 0;
Int32.TryParse(textBox1.Text, out val);
InputVal.SetResult(val);
}
}
The Form1UserInput class is instanced by Form1. The container is a Panel set by Form1 before being provided to the invoking class.
public interface IUserInput
{
Task<int> GetInteger();
}
public class Form1UserInput : IUserInput
{
public Control container;
private IntegerInput integerInput = new IntegerInput();
public IntegerInput IntegerInput { get { return integerInput; } }
public async Task<int> GetInteger()
{
container.Invoke(new Action(() =>
{
container.Controls.Clear();
container.Controls.Add(integerInput);
}));
await integerInput.InputVal.Task;
return integerInput.InputVal.Task.Result;
}
}
The Demo class contains the method I want to invoke.
public class Demo
{
public IUserInput ui;
public async void MethodToInvoke()
{
// Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
// Interface with hardware some more...
}
public async void AnotherMethodToInvoke()
{
// Interface with hardware...
// Block waiting on multiple input
int val1 = await ui.getInteger();
int val2 = await ui.getInteger();
// Interface with hardware...
}
}
This is a rough outline of what the invoking class looks like. The call to Task.Run() is accurate for my prototype.
public class Invoker
{
public async Task RunTestAsync(IUserInput ui)
{
object DemoInstance = Activator.CreateInstance(typeof(Demo));
MethodInfo method = typeof(Demo).GetMethod("MethodToInvoke");
object[] args = null;
((IUserInput)DemoInstance).ui = ui;
var t = await Task.Run(() => method.Invoke(DemoInstance, args));
// Report completion information back to Form1
}
}
The Form1 controller class instances the Invoker and calls RunTestAsync passing in an instance of Form1UserInput.
I am aware of some concerns about long running Tasks that may block and what that would mean for ThreadPool resources. However, the ability to invoke multiple methods at once is not provided by the application I am building. It's possible that the application may provide some other limited functionality while the invoked method is running but the current requirements do not specify such functionality in detail. I anticipate that there would only be one long running thread in service at any time.
Is the use of Task.Run() for this type of method invocation a reasonable implementation? If not, what would a more reasonable implementation be that provides for the required criteria? Should I consider a dedicated thread outside of the ThreadPool for this invocation?
Is the use of Task.Run() for this type of method invocation a reasonable implementation?
Assuming that your "interface with hardware" can only be done using synchronous APIs, then yes, Task.Run is fine for that.
However, I would change when it's called. Right now, Task.Run is wrapping an async void method that executes on the thread pool (and uses Invoke to jump back on the UI thread). These are each problematic: Task.Run over async void will seem to complete "early" (i.e., at the first await); and using Invoke indicates that there's some tight coupling going on (UI calls background service which calls UI).
I would replace the async void with async Task and also change where Task.Run is used to avoid Invoke:
public async Task<int> GetInteger()
{
container.Controls.Clear();
container.Controls.Add(integerInput);
// Note: not `Result`, which will wrap exceptions.
return await integerInput.InputVal.Task;
}
public async Task MethodToInvokeAsync()
{
await Task.Run(...); // Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
await Task.Run(...); // Interface with hardware some more...
}
var t = await (Task)method.Invoke(DemoInstance, args);

Call async task method from another class using wpf/C# [duplicate]

I have a public async void Foo() method that I want to call from synchronous method. So far all I have seen from MSDN documentation is calling async methods via async methods, but my whole program is not built with async methods.
Is this even possible?
Here's one example of calling these methods from an asynchronous method:
Walkthrough: Accessing the Web by Using Async and Await (C# and Visual Basic)
Now I'm looking into calling these async methods from sync methods.
Asynchronous programming does "grow" through the code base. It has been compared to a zombie virus. The best solution is to allow it to grow, but sometimes that's not possible.
I have written a few types in my Nito.AsyncEx library for dealing with a partially-asynchronous code base. There's no solution that works in every situation, though.
Solution A
If you have a simple asynchronous method that doesn't need to synchronize back to its context, then you can use Task.WaitAndUnwrapException:
var task = MyAsyncMethod();
var result = task.WaitAndUnwrapException();
You do not want to use Task.Wait or Task.Result because they wrap exceptions in AggregateException.
This solution is only appropriate if MyAsyncMethod does not synchronize back to its context. In other words, every await in MyAsyncMethod should end with ConfigureAwait(false). This means it can't update any UI elements or access the ASP.NET request context.
Solution B
If MyAsyncMethod does need to synchronize back to its context, then you may be able to use AsyncContext.RunTask to provide a nested context:
var result = AsyncContext.RunTask(MyAsyncMethod).Result;
*Update 4/14/2014: In more recent versions of the library the API is as follows:
var result = AsyncContext.Run(MyAsyncMethod);
(It's OK to use Task.Result in this example because RunTask will propagate Task exceptions).
The reason you may need AsyncContext.RunTask instead of Task.WaitAndUnwrapException is because of a rather subtle deadlock possibility that happens on WinForms/WPF/SL/ASP.NET:
A synchronous method calls an async method, obtaining a Task.
The synchronous method does a blocking wait on the Task.
The async method uses await without ConfigureAwait.
The Task cannot complete in this situation because it only completes when the async method is finished; the async method cannot complete because it is attempting to schedule its continuation to the SynchronizationContext, and WinForms/WPF/SL/ASP.NET will not allow the continuation to run because the synchronous method is already running in that context.
This is one reason why it's a good idea to use ConfigureAwait(false) within every async method as much as possible.
Solution C
AsyncContext.RunTask won't work in every scenario. For example, if the async method awaits something that requires a UI event to complete, then you'll deadlock even with the nested context. In that case, you could start the async method on the thread pool:
var task = Task.Run(async () => await MyAsyncMethod());
var result = task.WaitAndUnwrapException();
However, this solution requires a MyAsyncMethod that will work in the thread pool context. So it can't update UI elements or access the ASP.NET request context. And in that case, you may as well add ConfigureAwait(false) to its await statements, and use solution A.
Update, 2019-05-01: The current "least-worst practices" are in an MSDN article here.
Adding a solution that finally solved my problem, hopefully saves somebody's time.
Firstly read a couple articles of Stephen Cleary:
Async and Await
Don't Block on Async Code
From the "two best practices" in "Don't Block on Async Code", the first one didn't work for me and the second one wasn't applicable (basically if I can use await, I do!).
So here is my workaround: wrap the call inside a Task.Run<>(async () => await FunctionAsync()); and hopefully no deadlock anymore.
Here is my code:
public class LogReader
{
ILogger _logger;
public LogReader(ILogger logger)
{
_logger = logger;
}
public LogEntity GetLog()
{
Task<LogEntity> task = Task.Run<LogEntity>(async () => await GetLogAsync());
return task.Result;
}
public async Task<LogEntity> GetLogAsync()
{
var result = await _logger.GetAsync();
// more code here...
return result as LogEntity;
}
}
Microsoft built an AsyncHelper (internal) class to run Async as Sync. The source looks like:
internal static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return AsyncHelper._myTaskFactory
.StartNew<Task<TResult>>(func)
.Unwrap<TResult>()
.GetAwaiter()
.GetResult();
}
public static void RunSync(Func<Task> func)
{
AsyncHelper._myTaskFactory
.StartNew<Task>(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
The Microsoft.AspNet.Identity base classes only have Async methods and in order to call them as Sync there are classes with extension methods that look like (example usage):
public static TUser FindById<TUser, TKey>(this UserManager<TUser, TKey> manager, TKey userId) where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
return AsyncHelper.RunSync<TUser>(() => manager.FindByIdAsync(userId));
}
public static bool IsInRole<TUser, TKey>(this UserManager<TUser, TKey> manager, TKey userId, string role) where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
return AsyncHelper.RunSync<bool>(() => manager.IsInRoleAsync(userId, role));
}
For those concerned about the licensing terms of code, here is a link to very similar code (just adds support for culture on the thread) that has comments to indicate that it is MIT Licensed by Microsoft. https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Core/AsyncHelper.cs
Wouldn't this be the same as just calling Task.Run(async ()=> await AsyncFunc()).Result? AFAIK, Microsoft is now discouraging from calling TaskFactory.StartNew, since they are both equivalent and one is more readable than the other.
Absolutely not.
The easy answer is that
.Unwrap().GetAwaiter().GetResult() != .Result
First off the
Is Task.Result the same as .GetAwaiter.GetResult()?
Secondly .Unwrap() causes the setup of the Task not to block the wrapped task.
Which should lead anyone to ask
Wouldn't this be the same as just calling Task.Run(async ()=> await AsyncFunc()).GetAwaiter().GetResult()
Which would then be a It Depends.
Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew()
Excerpt:
Task.Run uses TaskCreationOptions.DenyChildAttach which means that children's tasks can not be attached to the parent and it uses TaskScheduler.Default which means that the one that runs tasks on Thread Pool will always be used to run tasks.
Task.Factory.StartNew uses TaskScheduler.Current which means scheduler of the current thread, it might be TaskScheduler.Default but not always.
Additional Reading:
Specifying a synchronization context
ASP.NET Core SynchronizationContext
For extra safety, wouldn't it be better to call it like this AsyncHelper.RunSync(async () => await AsyncMethod().ConfigureAwait(false)); This way we're telling the "inner" method "please don't try to sync to upper context and dealock"
Really great point and as most object architectural questions go it depends.
As an extension method do you want to force that for absolutely every call, or do you let the programmer using the function configure that on their own async calls? I could see a use case for call three scenarios; it most likely is not something you want in WPF, certainly makes sense in most cases, but considering there is no Context in ASP.Net Core if you could guarantee it was say internal for a ASP.Net Core, then it wouldn't matter.
async Main is now part of C# 7.2 and can be enabled in the projects advanced build settings.
For C# < 7.2, the correct way is:
static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
/*await stuff here*/
}
You'll see this used in a lot of Microsoft documentation, for example:
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions
I'm not 100% sure, but I believe the technique described in this blog should work in many circumstances:
You can thus use task.GetAwaiter().GetResult() if you want to directly invoke this propagation logic.
public async Task<string> StartMyTask()
{
await Foo()
// code to execute once foo is done
}
static void Main()
{
var myTask = StartMyTask(); // call your method which will return control once it hits await
// now you can continue executing code here
string result = myTask.Result; // wait for the task to complete to continue
// use result
}
You read the 'await' keyword as "start this long running task, then return control to the calling method". Once the long-running task is done, then it executes the code after it. The code after the await is similar to what used to be CallBack methods. The big difference being the logical flow is not interrupted which makes it much easier to write and read.
There is, however, a good solution that works in (almost: see comments) every situation: an ad-hoc message pump (SynchronizationContext).
The calling thread will be blocked as expected, while still ensuring that all continuations called from the async function don't deadlock as they'll be marshaled to the ad-hoc SynchronizationContext (message pump) running on the calling thread.
The code of the ad-hoc message pump helper:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Threading
{
/// <summary>Provides a pump that supports running asynchronous methods on the current thread.</summary>
public static class AsyncPump
{
/// <summary>Runs the specified asynchronous method.</summary>
/// <param name="asyncMethod">The asynchronous method to execute.</param>
public static void Run(Action asyncMethod)
{
if (asyncMethod == null) throw new ArgumentNullException("asyncMethod");
var prevCtx = SynchronizationContext.Current;
try
{
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(true);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function
syncCtx.OperationStarted();
asyncMethod();
syncCtx.OperationCompleted();
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
}
finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
}
/// <summary>Runs the specified asynchronous method.</summary>
/// <param name="asyncMethod">The asynchronous method to execute.</param>
public static void Run(Func<Task> asyncMethod)
{
if (asyncMethod == null) throw new ArgumentNullException("asyncMethod");
var prevCtx = SynchronizationContext.Current;
try
{
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(false);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function and alert the context to when it completes
var t = asyncMethod();
if (t == null) throw new InvalidOperationException("No task provided.");
t.ContinueWith(delegate { syncCtx.Complete(); }, TaskScheduler.Default);
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
t.GetAwaiter().GetResult();
}
finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
}
/// <summary>Runs the specified asynchronous method.</summary>
/// <param name="asyncMethod">The asynchronous method to execute.</param>
public static T Run<T>(Func<Task<T>> asyncMethod)
{
if (asyncMethod == null) throw new ArgumentNullException("asyncMethod");
var prevCtx = SynchronizationContext.Current;
try
{
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(false);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function and alert the context to when it completes
var t = asyncMethod();
if (t == null) throw new InvalidOperationException("No task provided.");
t.ContinueWith(delegate { syncCtx.Complete(); }, TaskScheduler.Default);
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
return t.GetAwaiter().GetResult();
}
finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
}
/// <summary>Provides a SynchronizationContext that's single-threaded.</summary>
private sealed class SingleThreadSynchronizationContext : SynchronizationContext
{
/// <summary>The queue of work items.</summary>
private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> m_queue =
new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
/// <summary>The processing thread.</summary>
private readonly Thread m_thread = Thread.CurrentThread;
/// <summary>The number of outstanding operations.</summary>
private int m_operationCount = 0;
/// <summary>Whether to track operations m_operationCount.</summary>
private readonly bool m_trackOperations;
/// <summary>Initializes the context.</summary>
/// <param name="trackOperations">Whether to track operation count.</param>
internal SingleThreadSynchronizationContext(bool trackOperations)
{
m_trackOperations = trackOperations;
}
/// <summary>Dispatches an asynchronous message to the synchronization context.</summary>
/// <param name="d">The System.Threading.SendOrPostCallback delegate to call.</param>
/// <param name="state">The object passed to the delegate.</param>
public override void Post(SendOrPostCallback d, object state)
{
if (d == null) throw new ArgumentNullException("d");
m_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
}
/// <summary>Not supported.</summary>
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("Synchronously sending is not supported.");
}
/// <summary>Runs an loop to process all queued work items.</summary>
public void RunOnCurrentThread()
{
foreach (var workItem in m_queue.GetConsumingEnumerable())
workItem.Key(workItem.Value);
}
/// <summary>Notifies the context that no more work will arrive.</summary>
public void Complete() { m_queue.CompleteAdding(); }
/// <summary>Invoked when an async operation is started.</summary>
public override void OperationStarted()
{
if (m_trackOperations)
Interlocked.Increment(ref m_operationCount);
}
/// <summary>Invoked when an async operation is completed.</summary>
public override void OperationCompleted()
{
if (m_trackOperations &&
Interlocked.Decrement(ref m_operationCount) == 0)
Complete();
}
}
}
}
Usage:
AsyncPump.Run(() => FooAsync(...));
More detailed description of the async pump is available here.
To anyone paying attention to this question anymore...
If you look in Microsoft.VisualStudio.Services.WebApi there's a class called TaskExtensions. Within that class you'll see the static extension method Task.SyncResult(), which like totally just blocks the thread till the task returns.
Internally it calls task.GetAwaiter().GetResult() which is pretty simple, however it's overloaded to work on any async method that return Task, Task<T> or Task<HttpResponseMessage>... syntactic sugar, baby... daddy's got a sweet tooth.
It looks like ...GetAwaiter().GetResult() is the MS-official way to execute async code in a blocking context. Seems to work very fine for my use case.
var result = Task.Run(async () => await configManager.GetConfigurationAsync()).ConfigureAwait(false);
OpenIdConnectConfiguration config = result.GetAwaiter().GetResult();
Or use this:
var result=result.GetAwaiter().GetResult().AccessToken
You can call any asynchronous method from synchronous code, that is, until you need to await on them, in which case they have to be marked as async too.
As a lot of people are suggesting here, you could call Wait() or Result on the resulting task in your synchronous method, but then you end up with a blocking call in that method, which sort of defeats the purpose of async.
If you really can't make your method async and you don't want to lock up the synchronous method, then you're going to have to use a callback method by passing it as parameter to the ContinueWith() method on task.
Inspired by some of the other answers, I created the following simple helper methods:
public static TResult RunSync<TResult>(Func<Task<TResult>> method)
{
var task = method();
return task.GetAwaiter().GetResult();
}
public static void RunSync(Func<Task> method)
{
var task = method();
task.GetAwaiter().GetResult();
}
They can be called as follows (depending on whether you are returning a value or not):
RunSync(() => Foo());
var result = RunSync(() => FooWithResult());
Note that the signature in the original question public async void Foo() is incorrect. It should be public async Task Foo() as you should return Task not void for async methods that don't return a value (yes, there are some rare exceptions).
Stephen Cleary's Answer;
That approach shouldn't cause a deadlock (assuming that
ProblemMethodAsync doesn't send updates to the UI thread or anything
like that). It does assume that ProblemMethodAsync can be called on a
thread pool thread, which is not always the case.
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
And here is the approach;
The Thread Pool Hack A similar approach to the Blocking Hack is to
offload the asynchronous work to the thread pool, then block on the
resulting task. The code using this hack would look like the code
shown in Figure 7.
Figure 7 Code for the Thread Pool Hack
C#
public sealed class WebDataService : IDataService
{
public string Get(int id)
{
return Task.Run(() => GetAsync(id)).GetAwaiter().GetResult();
}
public async Task<string> GetAsync(int id)
{
using (var client = new WebClient())
return await client.DownloadStringTaskAsync(
"https://www.example.com/api/values/" + id);
}
}
The call to Task.Run executes the asynchronous method on a thread pool
thread. Here it will run without a context, thus avoiding the
deadlock. One of the problems with this approach is the asynchronous
method can’t depend on executing within a specific context. So, it
can’t use UI elements or the ASP.NET HttpContext.Current.
Here is the simplest solution. I saw it somewhere on the Internet, I didn't remember where, but I have been using it successfully. It will not deadlock the calling thread.
void SynchronousFunction()
{
Task.Run(Foo).Wait();
}
string SynchronousFunctionReturnsString()
{
return Task.Run(Foo).Result;
}
string SynchronousFunctionReturnsStringWithParam(int id)
{
return Task.Run(() => Foo(id)).Result;
}
After hours of trying different methods, with more or less success, this is what I ended with. It doesn't end in a deadlock while getting result and it also gets and throws the original exception and not the wrapped one.
private ReturnType RunSync()
{
var task = Task.Run(async () => await myMethodAsync(agency));
if (task.IsFaulted && task.Exception != null)
{
throw task.Exception;
}
return task.Result;
}
You can now use source generators to create a sync version of your method using Sync Method Generator library (nuget).
Use it as follows:
[Zomp.SyncMethodGenerator.CreateSyncVersion]
public async void FooAsync()
Which will generate Foo method which you can call synchronously.
Those windows async methods have a nifty little method called AsTask(). You can use this to have the method return itself as a task so that you can manually call Wait() on it.
For example, on a Windows Phone 8 Silverlight application, you can do the following:
private void DeleteSynchronous(string path)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Task t = localFolder.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask();
t.Wait();
}
private void FunctionThatNeedsToBeSynchronous()
{
// Do some work here
// ....
// Delete something in storage synchronously
DeleteSynchronous("pathGoesHere");
// Do other work here
// .....
}
Hope this helps!
If you want to run it Sync
MethodAsync().RunSynchronously()

Categories