How to return on Task<int>? - c#

I've this code:
static void Main(string[] args)
{
// start import process
Task<int> task = StartImportProcess();
task.Wait();
// check result
// process finished
Console.ReadKey();
}
static async Task<int> StartImportProcess()
{
int result = 0;
result = await ImportCustomers();
// some other async/await operations
return result;
}
static Task<int> ImportCustomers()
{
// some heavy operations
Thread.Sleep(1000);
return 1; // <<< what should I return?
}
Using Task and async/await. I'd like to return an int as result of the task. Which object whould I return? return 1; won't work.

You should use Task.FromResult, (and don't use Thread.Sleep from a Task):
static async Task<int> ImportCustomers()
{
// some heavy operations
await Task.Delay(1000);
// Already awaited, so we can return the result as-is.
return 1;
// Or: if not already awaited anything,
// and also with non-async tasks, use:
return Task.FromResult(1);
}

Related

How to pause task running on a worker thread and wait for user input?

If I have a task running on a worker thread and when it finds something wrong, is it possible to pause and wait for the user to intervene before continuing?
For example, suppose I have something like this:
async void btnStartTask_Click(object sender, EventArgs e)
{
await Task.Run(() => LongRunningTask());
}
// CPU-bound
bool LongRunningTask()
{
// Establish some connection here.
// Do some work here.
List<Foo> incorrectValues = GetIncorrectValuesFromAbove();
if (incorrectValues.Count > 0)
{
// Here, I want to present the "incorrect values" to the user (on the UI thread)
// and let them select whether to modify a value, ignore it, or abort.
var confirmedValues = WaitForUserInput(incorrectValues);
}
// Continue processing.
}
Is it possible to substitute WaitForUserInput() with something that runs on the UI thread, waits for the user's intervention, and then acts accordingly? If so, how? I'm not looking for complete code or anything; if someone could point me in the right direction, I would be grateful.
What you're looking for is almost exactly Progress<T>, except you want to have the thing that reports progress get a task back with some information that they can await and inspect the results of. Creating Progress<T> yourself isn't terribly hard., and you can reasonably easily adapt it so that it computes a result.
public interface IPrompt<TResult, TInput>
{
Task<TResult> Prompt(TInput input);
}
public class Prompt<TResult, TInput> : IPrompt<TResult, TInput>
{
private SynchronizationContext context;
private Func<TInput, Task<TResult>> prompt;
public Prompt(Func<TInput, Task<TResult>> prompt)
{
context = SynchronizationContext.Current ?? new SynchronizationContext();
this.prompt += prompt;
}
Task<TResult> IPrompt<TResult, TInput>.Prompt(TInput input)
{
var tcs = new TaskCompletionSource<TResult>();
context.Post(data => prompt((TInput)data)
.ContinueWith(task =>
{
if (task.IsCanceled)
tcs.TrySetCanceled();
if (task.IsFaulted)
tcs.TrySetException(task.Exception.InnerExceptions);
else
tcs.TrySetResult(task.Result);
}), input);
return tcs.Task;
}
}
Now you simply need to have an asynchronous method that accepts the data from the long running process and returns a task with whatever the user interface's response is.
You can use TaskCompletionSource to generate a task that can be awaited within the LongRunningTask.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ConsoleApp5
{
class Program
{
private static event Action<string> Input;
public static async Task Main(string[] args)
{
var inputTask = InputTask();
var longRunningTask = Task.Run(() => LongRunningTask());
await Task.WhenAll(inputTask, longRunningTask);
}
private static async Task InputTask()
{
await Task.Yield();
while(true)
{
var input = await Console.In.ReadLineAsync();
Input?.Invoke(input);
}
}
static async Task<bool> LongRunningTask()
{
SomeExpensiveCall();
var incorrectValues = GetIncorrectValuesFromAbove();
if (incorrectValues.Count > 0)
{
var confirmedValues = await WaitForUserInput(incorrectValues).ConfigureAwait(false);
}
// Continue processing.
return true;
}
private static void SomeExpensiveCall()
{
}
private static Task<string> WaitForUserInput(IList<string> incorrectValues)
{
var taskCompletionSource = new TaskCompletionSource<string>();
Console.Write("Input Data: ");
try
{
void EventHandler(string input)
{
Input -= EventHandler;
taskCompletionSource.TrySetResult(input);
}
Input += EventHandler;
}
catch(Exception e)
{
taskCompletionSource.TrySetException(e);
}
return taskCompletionSource.Task;
}
private static IList<string> GetIncorrectValuesFromAbove()
{
return new List<string> { "Test" };
}
}
}
Of course in this example you could have just called await Console.In.ReadLineAsync() directly, but this code is to simulate an environment where you only have an event based API.
There are several ways to solve this problem, with the Control.Invoke being probably the most familiar. Here is a more TPL-ish approach. You start by declaring a UI related scheduler as a class field:
private TaskScheduler _uiScheduler;
Then initialize it:
public MyForm()
{
InitializeComponent();
_uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
Then you convert your synchronous LongRunning method to an asynchronous method. This means that it must return Task<bool> instead of bool. It must also have the async modifier, and by convention be named with the Async suffix:
async Task<bool> LongRunningAsync()
Finally you use the await operator in order to wait for the user's input, which will be a Task configured to run on the captured UI scheduler:
async Task<bool> LongRunningAsync()
{
// Establish some connection here.
// Do some work here.
List<Foo> incorrectValues = GetIncorrectValuesFromAbove();
if (incorrectValues.Count > 0)
{
// Here, I want to present the "incorrect values" to the user (on the UI thread)
// and let them select whether to modify a value, ignore it, or abort.
var confirmedValues = await Task.Factory.StartNew(() =>
{
return WaitForUserInput(incorrectValues);
}, default, TaskCreationOptions.None, _uiScheduler);
}
// Continue processing.
}
Starting the long running task is the same as before. The Task.Run understands async delegates, so you don't have to do something special after making the method async.
var longRunningTask = Task.Run(() => LongRunningAsync());
This should be enough, provided that you just intend to show a dialog box to the user. The Form.ShowDialog is a blocking method, so the WaitForUserInput method needs not to be asynchronous. If you had to allow the user to interact freely with the main form, the problem would be much more difficult to solve.
Another example using Invoke() and a ManualResetEvent. Let me know if you need help with the form code; setting up a constructor, using DialogResult, or creating a property to hold the "confirmedValues":
bool LongRunningTask()
{
// Establish some connection here.
// Do some work here.
List<Foo> incorrectValues = GetIncorrectValuesFromAbove();
var confirmedValues;
if (incorrectValues.Count > 0)
{
DialogResult result;
ManualResetEvent mre = new ManualResetEvent(false);
this.Invoke((MethodInvoker)delegate
{
// pass in incorrectValues to the form
// you'll have to build a constructor in it to accept them
frmSomeForm frm = new frmSomeForm(incorrectValues);
result = frm.ShowDialog();
if (result == DialogResult.OK)
{
confirmedValues = frm.confirmedValues; // get the confirmed values somehow
}
mre.Set(); // release the block below
});
mre.WaitOne(); // blocks until "mre" is set
}
// Continue processing.
}

Can not get results of TaskCompletionSource

Hello I have the following problem:
I want to perform something similar to a transaction. I want to execute a number of async operations after I receive an external trigger.Therefore I am using a TaskCompletionSource that gets set in a method representing the trigger :TriggerTransaction.This trigger method gets called in Main on the thread pool when i press a specific console key.
After I press the A keyword the TriggerTransaction gets executed and the TaskCompletionSource-s get set.Still the main thread does not compute the sum of the two awaited tasks.
class Program
{
public static Task<Task<int>> TransactionOperation1()
{
TaskCompletionSource<Task<int>> tcs = new TaskCompletionSource<Task<int>>();
tasks.Add(tcs);
Task<Task<int>> result = tcs.Task;
return result;
}
public static Task<Task<int>> TransactionOperation2()
{
TaskCompletionSource<Task<int>> tcs = new TaskCompletionSource<Task<int>>();
tasks.Add(tcs);
Task<Task<int>> result = tcs.Task;
return result;
}
public static async Task<int> ExecuteTransactionOnDB()
{
await Task.Delay(1000);
return 5;
}
public static async Task TriggerTransaction()
{
int value = await ExecuteTransactionOnDB();
foreach (var item in tasks)
{
item.SetResult(value);
}
}
public static List<dynamic> tasks = new List<dynamic>();
static async Task Main(string[] args)
{
Task<Task<int>> a = TransactionOperation1();
Task<Task<int>> b = TransactionOperation2();
Task.Run(async() =>
{
while (Console.ReadKey().Key != ConsoleKey.A) ;
await TriggerTransaction();
});
if (!File.Exists("D:\\data.txt"))
{
File.Create("D:\\data.txt");
}
using(FileStream stream=new FileStream("data.txt",FileMode.Append,FileAccess.Write))
{
int sum=await await a + await await b;//thread wont pass this line when tasks are set.
ReadOnlyMemory<byte> bytes = Encoding.UTF8.GetBytes(sum);
stream.Write(bytes.ToArray());
}
Console.WriteLine(await await a + await await b);
}
}
}
P.S If you are wondering why I did use a List<dynamic> to store the TaskCompletionSource-s ,it's because the TransactionOperations will differ in return type.Some of them will return int,others String ..Bool..etc.
For a better understanding i made a schema-
As you will see there are:
-A list where i want to store the TCS-es
-Some Calls that are completed only after the external trigger was set(the transaction was executed)
As you can see in the Calls,all have different return types.
Why would you need a Task<Task<int>>? Simply Task<int> is enough, and accordingly, TaskCompletionSource<int>. And you also get rid of an awkward await await ..., which isn't required in your case either.
Note that I also added Close() to the stream returned by File.Create().
Here is a working version of the program:
class Program
{
public static Task<int> TransactionOperation1()
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
tasks.Add(tcs);
return tcs.Task;
}
public static Task<int> TransactionOperation2()
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
tasks.Add(tcs);
return tcs.Task;
}
public static async Task<int> ExecuteTransactionOnDB()
{
await Task.Delay(1000);
return 5;
}
public static async Task TriggerTransaction()
{
int value = await ExecuteTransactionOnDB();
foreach (var item in tasks)
{
item.SetResult(value);
}
}
public static List<dynamic> tasks = new List<dynamic>();
static async Task Main(string[] args)
{
Task<int> a = TransactionOperation1();
Task<int> b = TransactionOperation2();
Task input = Task.Run(async () => {
while (Console.ReadKey().Key != ConsoleKey.A);
await TriggerTransaction();
});
if (!File.Exists("C:\\temp\\data.txt"))
{
File.Create("C:\\temp\\data.txt").Close();
}
using (FileStream stream = new FileStream("C:\\temp\\data.txt", FileMode.Append, FileAccess.Write))
{
int sum = await a + await b; // now it works ok
var bytes = Encoding.UTF8.GetBytes(sum.ToString());
stream.Write(bytes);
}
Console.WriteLine(await a + await b);
}
}
Check out the modified version of the code, it produce the expected result, by executing the Task created using TaskCompletionSource. I have made the code the Generic too, so that you don't need to use the dynamic type and define the datatype at the compile time
static async Task Main(string[] args)
{
var a = Program<int>.TransactionOperation1();
var b = Program<int>.TransactionOperation2();
await Task.Run(async() =>
{
Console.ReadLine();
await Program<int>.TriggerTransaction(5);
});
if (!File.Exists("D:\\data.txt"))
{
File.Create("D:\\data.txt");
}
using (FileStream stream = new FileStream("D:\\data.txt", FileMode.Append, FileAccess.Write))
{
int sum = await a + await b;//thread wont pass this line when tasks are set.
var bytes = Encoding.UTF8.GetBytes(sum.ToString());
stream.Write(bytes, 0, bytes.Length);
}
Console.WriteLine(await a + await b);
}
class Program<T>
{
public static Task<T> TransactionOperation1()
{
var tcs = new TaskCompletionSource<T>();
tasks.Add(tcs);
return tcs.Task;
}
public static Task<T> TransactionOperation2()
{
var tcs = new TaskCompletionSource<T>();
tasks.Add(tcs);
return tcs.Task;
}
public static async Task<T> ExecuteTransactionOnDB(T t)
{
return await Task.FromResult(t);
}
public static async Task TriggerTransaction(T t)
{
T value = await ExecuteTransactionOnDB(t);
foreach (var item in tasks)
{
item.SetResult(value);
}
}
public static List<TaskCompletionSource<T>> tasks = new List<TaskCompletionSource<T>>();
}
Following are the important modifications:
List<dynamic> is replaced by List<TaskCompletionSource<T>>
TransactionOperation1/2 have return type Task<T>, which is the Task created using the TaskCompletionSource<T>
Added an extra await to the Task.Run, which executes the TriggerTransaction internally, though you can replace the following code:
await Task.Run(async() =>
{
Console.ReadLine();
await Program<int>.TriggerTransaction(5);
});
with
await Program<int>.TriggerTransaction(5);
Now it produces the result as you expect, it will sum up the two integers. Few more small changes like removing Task.Delay, which is not required
EDIT 1 - Using Task.WhenAll
static async Task Main(string[] args)
{
var a = Program.TransactionOperation1(5);
var b = Program.TransactionOperation1(5);
Console.ReadLine();
var taskResults = await Task.WhenAll(a,b);
dynamic finalResult = 0;
foreach(var t in taskResults)
finalResult += t;
if (!File.Exists("D:\\data.txt"))
{
File.Create("D:\\data.txt");
}
using (FileStream stream = new FileStream("D:\\data.txt", FileMode.Append, FileAccess.Write))
{
var bytes = Encoding.UTF8.GetBytes(finalResult.ToString());
stream.Write(bytes, 0, bytes.Length);
}
Console.WriteLine(finalResult);
}
class Program
{
public static Task<dynamic> TransactionOperation1(dynamic val)
{
return Task<dynamic>.Run(() => val);
}
public static Task<dynamic> TransactionOperation2(dynamic val)
{
return Task<dynamic>.Run(() => val);
}
}

Wrapping a Task to return a value

I feel like there is a better way to do the following and looking for other opinions.
Essentially, I am trying to utilize the async/await pattern but need to return a bool value from method to indicate what happened in the method which is causing me to wrap the Task with Task so this can be accomplished. My spidey-sense is telling me something is wrong with my implementation.
In the below example "LongRunningTask" is something I don't have control over because it is a library method that returns a Task, so something I can't change. The remainder of the flow logic could be changed. Obviously, this is just a fictional representation of my real-issue but meant to demonstrate the issue, so don't get caught-up in the hard-coded "GetData", etc...
Take a look and let me know of other options.
void Main()
{
StartApplication();
}
private async void StartApplication()
{
// This is a just fictional example passing hard-coded GetData
var didExecuteLongRunningTask = await ProcessStuff("GetData");
if (didExecuteLongRunningTask)
{
Console.WriteLine("Long running task was executed");
}
else {
Console.WriteLine("Long running task was NOT executed");
}
}
// Define other methods and classes here
private async Task<bool> ProcessStuff(string command)
{
if (command == "GetData")
{
await LongRunningTask();
return await Task<bool>.Factory.StartNew(() => true);
}
else
{
return await Task<bool>.Factory.StartNew(() => false);
}
}
private Task LongRunningTask()
{
return Task.Delay(2000);
}
Yes, you are right, you are over-complicating it. You can just do:
private async Task<bool> ProcessStuff(string command)
{
if (command == "GetData")
{
await LongRunningTask();
return true;
}
else
{
return false;
}
}
You can look at the MSDN for more information: Asynchronous Programming

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