Waiting for all jobs to be finished with async await - c#

I'm trying to understand the usage of async-await in C#5. If I have 2 jobs started in a method, is there a best way to wait for their completion in C#5+ ? I've done the example below but I fail to see what the async await keywork brings here besides free documentation with async keyword.
I made the following example, I want "FINISHED !" to be printed last. It is not the case however. What did I miss ? How can I make the async method wait until all jobs are finished ? Is there a point using async-await here ? I could just do Task.WaitAll with a non-async method here. I don't really understand what async brings in case you want to wait.
class Program
{
static void Main(string[] args)
{
var fooWorker = new FooWorker();
var barWorker = new BarWorker();
var test = new Class1(fooWorker, barWorker);
test.SomeWork();
Console.ReadLine();
}
}
public class Foo
{
public Foo(string bar) => Bar = bar;
public string Bar { get; }
}
public class Class1
{
private IEnumerable<Foo> _foos;
private readonly FooWorker _fooWorker;
private readonly BarWorker _barWorker;
public Class1(FooWorker fooWorker, BarWorker barWorker)
{
_fooWorker = fooWorker;
_barWorker = barWorker;
}
public void SomeWork()
{
_foos = ProduceManyFoo();
MoreWork();
Console.WriteLine("FINISHED !");
}
private async void MoreWork()
{
if (_foos == null || !_foos.Any()) return;
var fooList = _foos.ToList();
Task fooWorkingTask = _fooWorker.Work(fooList);
Task barWorkingTask = _barWorker.Work(fooList);
await Task.WhenAll(fooWorkingTask, barWorkingTask);
}
private IEnumerable<Foo> ProduceManyFoo()
{
int i = 0;
if (++i < 100) yield return new Foo(DateTime.Now.ToString(CultureInfo.InvariantCulture));
}
}
public abstract class AWorker
{
protected virtual void DoStuff(IEnumerable<Foo> foos)
{
foreach (var foo in foos)
{
Console.WriteLine(foo.Bar);
}
}
public Task Work(IEnumerable<Foo> foos) => Task.Run(() => DoStuff(foos));
}
public class FooWorker : AWorker { }
public class BarWorker : AWorker { }

You are firing off tasks and just forgetting them, while the thread continues running. This fixes it.
Main:
static async Task Main(string[] args)
{
var fooWorker = new FooWorker();
var barWorker = new BarWorker();
var test = new Class1(fooWorker, barWorker);
await test.SomeWork();
Console.ReadLine();
}
SomeWork:
public async Task SomeWork()
{
_foos = ProduceManyFoo();
await MoreWork();
Console.WriteLine("FINISHED !");
}
MoreWork signature change:
private async Task MoreWork()
The obvious code smell which should help make the problem clear is using async void. Unless required this should always be avoided.
When using async and await you'll usually want to chain the await calls to the top-level (in this case Main).
await is non-blocking, so anything that calls an async method should really care about the Task being returned.

Related

Is this usage of Task.Run() bad practice?

If the use of Task.Run in this case justifiable ?
Currently I run this code in a WinForms app, but later on it will be used in a ASP.NET project as a HostedService/BackgroundService. I am not sure if this is comparable then.
After reading multiple blogs about async/await and Tasks I feel like the Task.Run(() => .. should be implemented in the calling method Manager.SyncLoop(). But what if the implementation of IConnection is truely asynchronous, wouldn't that be code smell ?
private async void button1_Click(object sender, EventArgs e)
{
// this should be handled by the BackgroudService, WinForms is used just for testing
var m = new Manager();
m.Connection = new ConnectionA();
m.ExecuteAsync();
}
}
public interface IConnection
{
Task<object> ReadAsync();
}
// assume that i cannot change this
public class SomeLib
{
private Random random = new Random();
public object SyncReading()
{
Thread.Sleep(5000);
return random.Next(); ;
}
}
public class ConnectionA : IConnection
{
private SomeLib lib = new SomeLib();
public Task<object> ReadAsync()
{
// is this usage of Task.Run ok?
var v = Task.Run(() => lib.SyncReading());
return v;
}
// this will block UI
//public Task<object> ReadAsync()
//{
// return Task.FromResult(lib.SyncReading());
//}
}
public class Manager
{
public IConnection Connection { get; set; }
public async Task ExecuteAsync()
{
await SyncLoop();
}
public async Task SyncLoop()
{
while (true)
{
var i = await Connection.ReadAsync();
await Task.Delay(2000);
}
}
}
First, can you change IConnection? Is this synchronous implementation the primary one, or is it just one of many?
If you can change IConnection, then make it synchronous, and you can use Task.Run in the implementation of ExecuteAsync.
If IConnection needs to remain asynchronous, then I would say to implement ConnectionA.ReadAsync synchronously. Then have the Task.Run in ExecuteAsync as normal. The key behind this technique is that an asynchronous (Task-returning) signature means that the implementation may be asynchronous, not that it must be asynchronous.

Async testing scenario fails when call made to command interface

I have a problem with testing an ICommand scenario in a Xamarin project. I have extracted the logic into a demonstration below.
Scenario N1 runs smoothly however I need Scenario N2 to work. The problem with scenario N2 is that as soon as it gets to the
await Task.Run(() => Task.Delay(1000));
it jumps back to the test method Assert where obviously the SetSurveyContext(int x) is not executed yet.
The strangest thing is that if I run this code from the Xamarin framework inside the app everything works fine probably because I am executing the Command in a wrong manner.
Really stuck with this question, I have tried numerous ways to run the command but neither have worked. Please help if someone has come across the same problem. Thanks.
Scenario 1 - working
[Test]
public async Task NewSurvey_SendObjectWithOnlyDate_StaticSurveyResourceIdAndDateSet()
{
var mvmTest = new TesterPage();
await mvmTest.NewSurvey();
Assert.That(mvmTest.setter, Is.EqualTo(3));
}
public partial class TesterPage : ContentPage
{
public int setter = 0;
public TesterPage()
{
InitializeComponent ();
}
public async Task NewSurvey()
{
await PostNewSurvey();
}
private async Task PostNewSurvey()
{
var response = await Another();
SetSurveyContext(response);
}
private async Task<int> Another()
{
await Task.Run(() => Task.Delay(1000));
return 3;
}
private void SetSurveyContext(int x)
{
setter = x;
}
}
Test green, everything runs smoothly.
Scenario N2 - fails
[Test]
public async Task NewSurvey_SendObjectWithOnlyDate_StaticSurveyResourceIdAndDateSet()
{
var mvmTest = new TesterPage();
mvmTest.NewSurveyCommand.Execute(null);
Assert.That(mvmTest.setter, Is.EqualTo(3));
}
public partial class TesterPage : ContentPage
{
public int setter = 0;
public TesterPage ()
{
InitializeComponent ();
NewSurveyCommand = new Command(async () => await NewSurvey());
}
public ICommand NewSurveyCommand { get; private set; }
public async Task NewSurvey()
{
await PostNewSurvey();
}
private async Task PostNewSurvey()
{
var response = await Another();
SetSurveyContext(response);
}
private async Task<int> Another()
{
await Task.Run(() => Task.Delay(1000));
return 3;
}
private void SetSurveyContext(int x)
{
setter = x;
}
}
Because I have solved this problem with #YuriZolotarev in chat, here the solution we found for everyone else who encounters it:
The problem:
When Task.Run() is called in TesterPage.Another() the main thread jumps back to the test method. There it executes Assert.That() immediately, even before SetSurveyContext has set setter to3.
The solution:
We found the solution to create a new private field in TesterPage which should contain the Task started in TesterPage.Another(). This Task can be waited for in the test method via Reflection. Everything could look like this:
[Test]
public async Task NewSurvey_SendObjectWithOnlyDate_StaticSurveyResourceIdAndDateSet()
{
var mvmTest = new TesterPage();
mvmTest.NewSurveyCommand.Execute(null);
// Use Reflection to wait for the task
(GetInstanceField(typeof(TesterPage), mvmTest, "runningTask") as Task).Wait();
Assert.That(mvmTest.setter, Is.EqualTo(3));
}
// A helper method to simplify Reflection
internal static object GetInstanceField(Type type, object instance, string fieldName)
{
BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Static;
FieldInfo field = type.GetField(fieldName, bindFlags);
return field.GetValue(instance);
}
public partial class TesterPage : ContentPage
{
public int setter = 0;
private Task runningTask; // The field our Task object is saved in
public TesterPage ()
{
InitializeComponent ();
NewSurveyCommand = new Command(async () => await (runningTask = NewSurvey()));
}
public ICommand NewSurveyCommand { get; private set; }
public async Task NewSurvey()
{
await PostNewSurvey();
}
private async Task PostNewSurvey()
{
var response = await Another();
SetSurveyContext(response);
}
private async Task<int> Another()
{
await Task.Run(() => Task.Delay(1000));
return 3;
}
private void SetSurveyContext(int x)
{
setter = x;
}
}

Locking according to Id in async method

I have MVC application in which action methods must be executed on certain order. Recently, I am having some strange issues and I suppose that it is due to the fact that I do not do any thread synchronization. I have barely worked with multithreading and I don't know much about it. I tried to implement some kind of locking where I have to lock according to Id. So I implemented class like below to get required lock objects.
public class ReportLockProvider
: IReportLockProvider
{
readonly ConcurrentDictionary<long, object> lockDictionary
= new ConcurrentDictionary<long, object>();
public object ProvideLockObject(long reportId)
{
return lockDictionary.GetOrAdd(reportId, new object());
}
}
I tried to use this as below:
ReportLockProvider lockProvider = new ReportLockProvider();
public async ActionResult MyAction(long reportId)
{
lock(lockProvider.ProvideLockObject(reportId))
{
// Some operations
await Something();
// Some operation
}
}
I hoped that it would work, but it event didn't compiled because I have used await inside lock body. I have searched a bit and came across to SemaphoreSlim in this answer. Now, the problem is that I have to get lock object according to Id. How can I do this? Is it OK to create multiple SemaphoreSlim objects? Is it OK if I modify code like below :
public class ReportLockProvider
: IReportLockProvider
{
readonly ConcurrentDictionary<long, SemaphoreSlim> lockDictionary
= new ConcurrentDictionary<long, SemaphoreSlim>();
public SemaphoreSlim ProvideLockObject(long reportId)
{
return lockDictionary.GetOrAdd(reportId, new SemaphoreSlim(1, 1));
}
}
public async ActionResult MyAction(long reportId)
{
var lockObject = ReportLockProvider.ProvideLockObject(reportId);
await lockObject.WaitAsync();
try
{
// Some operations
await Something();
// Some operation
}
finally
{
lockObject.Release();
}
}
The other question is that, can I use SemaphoreSlim in non-async methods? Is there any better option?
I think you are missing a static keyword in front of your lockDictionary, but it depends on how you instanciate the provider.
Here is a sample with a little change code I cooked up in LinqPad:
async Task Main()
{
ReportLockProvider reportLockProvider = new ReportLockProvider();
List<Task> tasks = new List<Task>(10);
for (long i = 1; i <= 5; i++) {
var local = i;
tasks.Add(Task.Run(() => Enter(local) ));
tasks.Add(Task.Run(() => Enter(local) ));
}
async Task Enter(long id)
{
Console.WriteLine(id + " waiting to enter");
await reportLockProvider.WaitAsync(id);
Console.WriteLine(id + " entered!");
Thread.Sleep(1000 * (int)id);
Console.WriteLine(id + " releasing");
reportLockProvider.Release(id);
}
await Task.WhenAll(tasks.ToArray());
}
public class ReportLockProvider
{
static readonly ConcurrentDictionary<long, SemaphoreSlim> lockDictionary = new ConcurrentDictionary<long, SemaphoreSlim>();
public async Task WaitAsync(long reportId)
{
await lockDictionary.GetOrAdd(reportId, new SemaphoreSlim(1, 1)).WaitAsync();
}
public void Release(long reportId)
{
SemaphoreSlim semaphore;
if (lockDictionary.TryGetValue(reportId, out semaphore))
{
semaphore.Release();
}
}
}

Learning C#'s async/await/Task structure; code hangs at await?

To get a sense for how C#'s threading constructs work, I've written a simple test program that performs the same task - sleeping for 3 seconds then returning an object - both synchronously and asynchronously. I've set up some stopwatches to get a better sense as to how the code is flowing.
The synchronous call is working as expected: there's a 3 sec delay between the "before sync" and "after sync" prints. However, for the async call, the program hangs indefinitely after "after async". I'm expecting "before async" and "after async" to print quickly in succession (since ExecuteAsync just returns a Task), then for "awaited async" to print three seconds later (or rather, at least three seconds later; if there was a ton of logic between ExecuteAsync and when that Task is awaited, it might be longer).
namespace TaskTest
{
class Program
{
static void Main(string[] args)
{
doStuff().Wait();
Console.WriteLine("Press any key to end");
Console.ReadKey();
}
static async Task doStuff()
{
TestClass tceOn = new TestClass(true);
Stopwatch s = Stopwatch.StartNew();
s.Checkpoint("Before sync on");
tceOn.ExecuteSync();
s.Checkpoint("After sync on");
Console.WriteLine();
s.Checkpoint("Before async on");
Task<Foo> fooTask = tceOn.ExecuteAsync();
s.Checkpoint("After async on");
Foo foo = await fooTask;
s.Checkpoint("Awaited async on");
}
}
class TestClass
{
public bool ShouldWait = false;
public TestClass(bool tce)
{
ShouldWait = tce;
}
public Task<Foo> ExecuteAsync()
{
Task<Foo> output;
RunExecute(out output, true);
return output;
}
public Foo ExecuteSync()
{
Task<Foo> dud;
return RunExecute(out dud);
}
private Foo RunExecute(out Task<Foo> task, bool async = false)
{
Foo outputFoo;
if(async)
{
task = new Task<Foo>(makeFoo);
outputFoo = null;
}
else
{
task = null;
outputFoo = makeFoo();
}
return outputFoo;
}
private Foo makeFoo()
{
if (ShouldWait)
Thread.Sleep(3000);
return new Foo();
}
}
class Foo { }
}
To clean it up a bit, I didn't paste the extension method for Stopwatch's Checkpoint() method; it just prints the number of ticks so I can get a sense for the time elapsed.
So, why isn't this code working as expected? I was hoping this would be a "simplest thing that could possibly work"-type scenario. Thanks!
Update:
Having changed my code according to Peter Duniho's first suggestion (task = Task.Run(() => makeFoo());), I'm now trying to figure out how to get this to work with a .ContinueWith() block:
private Foo RunExecute(out Task<Foo> task, bool async = false)
{
Foo outputFoo;
if(async)
{
task = Task.Run(() => makeFoo()).ContinueWith((t) => // **** error here ****
{
outputFoo = null;
});
}
else
{
task = null;
outputFoo = makeFoo();
}
return outputFoo;
}
This is giving me an implicit conversion error on the line where I made the change:
Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'System.Threading.Tasks.Task<TaskTest.Foo>'
Because I'm new to how Tasks, Actions, and the like work, I'm not quite sure what the problem is/what's not matching up.
You haven't actually run any Task. So you're waiting on something that will never complete.
To fix your code exactly as it is, you can do this:
private Foo RunExecute(out Task<Foo> task, bool async = false)
{
Foo outputFoo;
if(async)
{
task = Task.Run(() => makeFoo());
outputFoo = null;
}
else
{
task = null;
outputFoo = makeFoo();
}
return outputFoo;
}
A more idiomatic way would look something like this:
private Foo RunExecute(out Task<Foo> task, bool async = false)
{
Foo outputFoo;
if(async)
{
task = makeFooAsync();
outputFoo = null;
}
else
{
task = null;
outputFoo = makeFoo();
}
return outputFoo;
}
async Task<Foo> makeFooAsync()
{
await Task.Delay(3000);
return new Foo();
}
You can even change the example so that both the synchronous and asynchronous work exactly the same (and don't require the out parameter):
private Task<Foo> RunExecute(bool async = false)
{
Foo outputFoo;
if(async)
{
return makeFooAsync();
}
else
{
return Task.FromResult(makeFoo());
}
}
To get a sense for how C#'s threading constructs work, I've written a simple test program that performs the same task - sleeping for 3 seconds then returning an object - both synchronously and asynchronously.
Your actual code is quite complex. So let's start with the "simplest possible" 3-second synchronous sleep:
class Program
{
static void Main(string[] args)
{
TestClass tceOn = new TestClass();
Stopwatch s = Stopwatch.StartNew();
s.Checkpoint("Before sync on");
tceOn.Execute();
s.Checkpoint("After sync on");
Console.WriteLine("Press any key to end");
Console.ReadKey();
}
}
class TestClass
{
public Foo Execute()
{
Thread.Sleep(3000);
return new Foo();
}
}
class Foo { }
Now, to create an asynchronous equivalent, you first start at the "leaves" - in this case, Thread.Sleep in TestClass.Execute, and work your way up. This is the natural way to convert code to be asynchronous (except in this case, we're creating the asynchronous code side-by-side instead of in-place). The first step is always to identify blocking operations (Thread.Sleep) and discover asynchronous equivalents (in this case, Task.Delay):
class TestClass
{
public async Task<Foo> ExecuteAsync()
{
await Task.Delay(3000);
return new Foo();
}
public Foo Execute()
{
Thread.Sleep(3000);
return new Foo();
}
}
Note the similarities between the two methods. Also note that there is no need for Task.Run. This is the case for all naturally-asynchronous code.
At this point, you're ready to add the asynchronous test. Since Main can't be async, this is the point at which you need to move the test code to another method:
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
Console.WriteLine("Press any key to end");
Console.ReadKey();
}
static async Task MainAsync()
{
TestClass tceOn = new TestClass();
Stopwatch s = Stopwatch.StartNew();
s.Checkpoint("Before sync on");
tceOn.Execute();
s.Checkpoint("After sync on");
s.Checkpoint("Before async on");
Task<Foo> fooTask = tceOn.ExecuteAsync();
s.Checkpoint("After async on");
Foo foo = await fooTask;
s.Checkpoint("Awaited async on");
}
}
For your final question regarding ContinueWith, the answer is "don't use ContinueWith; use await instead".

Async Method does not return control back to caller

Control is returned back to main method, before UploadToServer executes completely. Should I remove Task.Run() from UploadToServer or do a WaitAll explicitly?
public class Uploader
{
async public Task<int> Upload(int i)
{
int incremented = 0;
var t = UploadToServer(i);
if (t != null)
{
incremented = await t;
}
return incremented;
}
async private Task<int> UploadToServer(int i)
{
int incremented = 0;
await Task.Run(() =>
{
//Console.ReadLine();
//Actual upload operation
incremented = i + 1;
});
return incremented;
}
}
class Program
{
static void Main(string[] args)
{
Uploader upl = new Uploader();
var res = upl.Upload(10).Result;
}
}
When you await on async methods, the control is yielded back to the caller. What you're experiencing is proper async behavior.
If you dont want the method to return while the operation is executing, execute it synchronously.
If what you're attempting to do is I/O bound work (like upload something to a server), dont use Task.Run, as I/O bound is naturally exposed with async endpoints, eliminating the need for unnecessary threads in the process. Look at HttpClient as an example which exposes a bunch of XXXAsync methods.
try in this way
private Task<int> UploadToServer(int i)
{
int incremented = 0;
return Task.Run(() =>
{
//Console.ReadLine();
//Actual upload operation
return incremented = i + 1;
});
}
or in this way
private async Task<int> UploadToServer(int i)
{
return await Task.Run(() => DoSomething(i)).Wait();
}
private int DoSomething(int i)
{
//Console.ReadLine();
//Actual upload operation
return i+1;
}
Note that these examples aren't particularly useful methods.
considers that the background thread should live its own life.
In your case I suppose that maybe you can use some async methods of the HttpClient class of the framework
Example
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.test.com/");
return html.Length;
}
UPDATE
I've tested this code and it worked
static void Main(string[] args)
{
Uploader upl = new Uploader();
var res = upl.Upload(10).Result;
}
public class Uploader
{
async public Task<int> Upload(int i)
{
int incremented = 0;
var t = UploadToServer(i);
if (t != null)
{
incremented = await t;
}
return incremented;
}
private async Task<int> UploadToServer(int i)
{
return await Task.Run(() => DoSomething(i));
}
private int DoSomething(int i)
{
//Console.ReadLine();
//Actual upload operation
Thread.Sleep(2000);
return i + 1;
}
}
main program waits 2 seconds before receive the right value and the control back.
Have a look at this Should I expose asynchronous wrappers for synchronous methods? article that explains when and how you should use asynchronous methods. In your specific example you aren't getting advantages from task.run. I have only provided to you one working example with your code.

Categories

Resources