I want to write a class to simplify the asynchronous programing, like string s = mylib.BeginInvoek(test,"1"); here is my code:
public T BeginInvokeExWithReturnValue<T>(Func<T> actionFunction)
{
ExecWithReturnType<T> execWtihReturnValue = new ExecWithReturnType<T>(actionFunction);
IAsyncResult iar = execWtihReturnValue.BeginInvoke(new AsyncCallback(EndInvokeExWithReturnValue<T>), execWtihReturnValue);
// how to code here to return value
}
private void EndInvokeExWithReturnValue<T>(IAsyncResult iar)
{
ExecWithReturnType<T> execWtihReturnValue = (ExecWithReturnType<T>)iar.AsyncState;
execWtihReturnValue.EndInvoke(iar);
}
this BeginInvokeExWithReturnValue function has no input parameter, but returns a value,
But I don't know how to return a value from BeginInvokeExWithReturnValue function. Anyone who know this, Could you pls help me ? thx very much.
What you are trying to do right now is not async; if you want to return the T, just use:
return actionFunction();
It will be less overhead.
If you want async, and you are on 4.0, then the TPL may be a good option:
public Task<T> BeginInvokeExWithReturnValue<T>(Func<T> actionFunction)
{
var task = new Task<T>(actionFunction);
task.Start();
return task;
}
Now the caller can use:
var task = BeginInvokeExWithReturnValue(() => Whatever());
and then when desired, check for completion, block (Wait) for completion, register continuations, etc. Or just:
var result = task.Result; // implicit wait
Console.WriteLine(result);
This allows you to seamlessly write async code. Or in C# 5.0, seamlessly write continuations:
var result = await task; // continuation - this is **not** a wait
Console.WriteLine(result);
As David pointed out, the Invoke method is probably what you want, but if you're looking to write you're own variant, you just need to type cast the value to the generic (T, in your example) to satisfy your comment.
return (T) iar;
Following from the comments,
There are 3 models of Asyncronous development in .NET
APM - (BeginXXX EndXXX) Which you are using here, when the long running task completes it calls back into your code in the EndXXX method
EAP - Event based. In this model, when the long running task completes, an event is raised to inform your code.
TPL - New in .NET 4, this is the 'Task' based version. it looks most like Syncronous programming to client code, using a fluent interface. Its calls back to your code using continueWith.
Hope this helps
Related
I am trying to you use yield and return a result from converting X into Y in an async task. But, I am getting an error on select.
The error is:
Error CS1942 The type of the expression in the select clause is
incorrect. Type inference failed in the call to 'Select'.
public async Task<Result<dynamic>> GetYAsync(IEnumerable<X> infos)
{
return Task.WhenAll(from info in infos.ToArray() select async ()=>
{
yield return await new Y(info.Id, "Start");
});
}
Short answer: you can't use an asynchronous yield statement.
But in most cases, you don't need to. Using LINQ you can aggregate all tasks before passing them into Task.WaitAll. I simplified your example to return an IEnumerable<int>, but this will work with every type.
public class Program
{
public static Task<int> X(int x)
{
return Task.FromResult(x);
}
public static async Task<IEnumerable<int>> GetYAsync(IEnumerable<int> infos)
{
var res = await Task.WhenAll(infos.Select(info => X(info)));
return res;
}
public static async void Main()
{
var test = await GetYAsync(new [] {1, 2, 3});
Console.WriteLine(test);
}
}
Your example has another error await new Y(...), a constructor cannot be asynchronous, therefore I replaced it with an asynchronous function. (As hinted in the comments, it is technically possible to create a custom awaitable type and create this type with new, although this is rarely used),
The example above uses infos.Select to create a list of pending tasks, returned by invoking the function X. This list of tasks will then be awaited and returned.
This workaround should fit most cases. Real asynchronous iterators, as for example in JavaScript, are not supported in .Net.
Update: This feature is currently suggested as a language proposal: Async Streams. So maybe we will see this in the future.
Update: If you need asynchronous iterators, there are a few options currently available:
Reactive Stream, RX.Net, which provides you with asynchronous observable streams based on events.
There are implementations of asynchronous iterators or asynchronous enumerables AsyncEnumerable or
.Net Async Enumerable
You do not. Async Enum support (and yield is there to implement enumerable) comes with C# 8 some point in 2019 as it looks. So, for now the answer is simply that you do not.
The reason you get the error is that you can also not returna Result. Yield (return) is specific to implementing enumerations. Your method signature does not match.
I have some code that is working fine but I don't understand why. My method performs some SQL operations using the ExecuteReaderAsync, ExecuteNonQueryAsync, and WriteToServerAsync. WriterToServerAsync is the last one I call.
I originally wrote the method with the signature public async void Run() but the Hangfire job runner I am using won't accept async unless it returns a Task. I changed the signature to async Task Run() and then tried to figure out how to return a Task from the method.
I thought that I could just return the same task that was being returned from WriteToServerAsync but this would not compile. I ended deleting the return statement altogether. The compiler does not complain and the method works fine.
public async Task Run()
{
// Start querying the source first as it is the slowest operation...
var sqlSourceConnection = new SqlConnection(sourceConnectionString);
// The query is kind of slow so it needs more than the default 30 second timeout...
var sqlSourceCommand = new SqlCommand(SourceDataSql, sqlSourceConnection) { CommandTimeout = 180 };
sqlSourceConnection.Open();
// Query the records from the source...
var querySourceDataTask = sqlSourceCommand.ExecuteReaderAsync();
// Delete existing records from target to make way for the new set...
var sqlTargetConnection = new SqlConnection(targetConnectionString);
sqlTargetConnection.Open();
var sqlTargetTransaction = sqlTargetConnection.BeginTransaction(IsolationLevel.ReadCommitted);
var deleteRowsTask = sqlDeleteCommand.ExecuteNonQueryAsync();
// Wait for the delete and query tasks to finish before attempting the bulk copy...
await Task.WhenAll(deleteRowsTask, querySourceDataTask);
await sqlBulkCopy.WriteToServerAsync(querySourceDataTask.Result);
}
Why does this compile and work without a return statement for the Task?
Why does this compile and work without a return statement for the Task?
Because the return type Task is the equivalent of void (a method that doesn't return any value) for an asynchronous method that can be awaited.
Please refer to the following links for more information about the async/await keywords in C#.
Async/Await - Best Practices in Asynchronous Programming: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
Asynchronous Programming with async and await (C#): https://msdn.microsoft.com/en-us/library/mt674882.aspx
I am looking for a simple way to do a task in background, then update something (on the main thread) when it completes. It's in a low level 'model' class so I can't call InvokeOnMainThread as I don't have an NSObject around. I have this method:
public void GetItemsAsync(Action<Item[]> handleResult)
{
Item[] items=null;
Task task=Task.Factory.StartNew(() =>
{
items=this.CreateItems(); // May take a second or two
});
task.ContinueWith(delegate
{
handleResult(items);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
This seems to work OK, but
1) Is this the best (simplest) way?
2) I'm worried about the local variable:
Item{} items=null
What stops that disappearing when the method returns before the background thread completes?
Thanks.
I think your method slightly violates a Single Responsibility Principle, because it doing too much.
First of all I suggest to change CreateItems to return Task instead of wrapping it in the GetItemsAsync:
public Task<Item[]> CreateItems(CancellationToken token)
{
return Task.Factory.StartNew(() =>
// obtaining the data...
{});
}
CancellationToken is optional but can help you if you able to cancel this long running operation.
With this method you can remove GetItemsAsync entirely because its so simple to handle results by your client without passing this delegate:
// Somewhere in the client of your class
var task = yourClass.CreateItems(token);
task.ContinueWith(t =>
// Code of the delegate that previously
// passed to GetItemsAsync method
{}, TaskScheduler.FromCurrentSynchronizationContext());
Using this approach you'll get more clear code with only one responsibility. Task class itself is a perfect tool for representing asynchronous operation as a first class object. Using proposed technique you can easily mock you current implementation with a fake behavior for unit testing without changing your clients code.
Something like this:
public void GetItemsAsync(Action<Item[]> handleResult)
{
int Id = 11;
Task<Item[]> task = Task.Factory.StartNew(() => CreateItems(Id)); // May take a second or two
task.ContinueWith(t => handleResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext());
}
Your code looks fine.
It's a perfect example of when to use async / await if you can use C# 5, but if not, you have to write it as you have done with continuations.
The items variable is captured in your lambdas, so that's fine too.
When you write a lambda that uses an outside variable, the C# compiler creates a class that contains the variable. This is called a closure and means you can access the variable inside your lambda.
Here is a nicer soultion:
public void GetItemsAsync(Action<Item[]> handleResult)
{
var task = Task.Factory.StartNew<Item[]>(() =>
{
return this.CreateItems(); // May take a second or two
});
task.ContinueWith(delegate
{
handleResult(task.Result);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
I have an async method:
public async Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, string language, bool throwEx = true)
{
UserLoginExResult result = await UserService.LoginExAsync(UserGroup, language, TimezoneOffset, GetDeviceInfo(), GetLoginProperties(), exRequest);
ProcessLoginResult(result, false, throwEx);
return result;
}
And an overload:
public Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, bool throwEx = true)
{
return LoginExAsync(exRequest, Language.ID, throwEx);
}
I'm not sure if I should mark the overloaded one (the one with fewer parameters) as async and use await? I guess I should not but can you tell me what whould happen if I would do that? I'm quite lost in here and not really sure what Task it would wait for? Would it create an extra Task or await doesn't create a new Task?
No, there's little benefit in using an async method when it's just going to wrap and unwrap an existing one. It's fine to just have a "normal" method here, delegating to the "real" async method.
(They're not quite the same - for example, if the UserService.LoginExAsync method throws an exception rather than returning a failed task, the async/await version will just return a failed task, whereas the other version will also throw immediately.)
The async keyword only enables the await keyword. In your case, you can return the Task directly, so there's no need for the async keyword. async would only add overhead without adding any value.
For more information, see Stephen Toub's Zen of Async talk. He addresses this situation directly.
It would really only be worth doing if you were doing additional work in your overload, e.g.
public async Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, bool throwEx = true)
{
Task<UserLoginExResult> result = await LoginExAsync(exRequest, Language.ID, throwEx);
//Do some work here that depends on the result from the task completeion
return result;
}
But as you are not, it isn't!
The overload doesn't need to be marked as async as it doesn't internally await anything, so therefore there's nothing for the compiler to rewrite.
How would you implement something that works similarly to the Async CTP await keyword? Is there a simple implementation that works like await in all cases, or does await require different implementations for different scenarios?
The new await keyword has similar semantics to the existing yield return keyword in that they both cause the compiler to generate the continuation style state machine for you. So it is possible to hack something together using iterators that has some of the same behaviors as the Async CTP.
Here is what it would look like.
public class Form1 : Form
{
private void Button1_Click(object sender, EventArgs e)
{
AsyncHelper.Invoke<bool>(PerformOperation);
}
private IEnumerable<Task> PerformOperation(TaskCompletionSource<bool> tcs)
{
Button1.Enabled = false;
for (int i = 0; i < 10; i++)
{
textBox1.Text = "Before await " + Thread.CurrentThread.ManagedThreadId.ToString();
yield return SomeOperationAsync(); // Await
textBox1.Text = "After await " + Thread.CurrentThread.ManagedThreadId.ToString();
}
Button2.Enabled = true;
tcs.SetResult(true); // Return true
}
private Task SomeOperationAsync()
{
// Simulate an asynchronous operation.
return Task.Factory.StartNew(() => Thread.Sleep(1000));
}
}
Since yield return generates an IEnumerable our coroutine must return an IEnumerable. All of the magic happens inside the AsyncHelper.Invoke method. This is what gets our coroutine (masquerading as a hacked iterator) going. It takes special care to make sure the iterator is always executed on the current synchronization context if one exists which is important when trying to simulate how await works on a UI thread. It does this by executing the first MoveNext synchronously and then using SynchronizationContext.Send to do the rest from a worker thread which is also used to asynchronously wait on the individual steps.
public static class AsyncHelper
{
public static Task<T> Invoke<T>(Func<TaskCompletionSource<T>, IEnumerable<Task>> method)
{
var context = SynchronizationContext.Current;
var tcs = new TaskCompletionSource<T>();
var steps = method(tcs);
var enumerator = steps.GetEnumerator();
bool more = enumerator.MoveNext();
Task.Factory.StartNew(
() =>
{
while (more)
{
enumerator.Current.Wait();
if (context != null)
{
context.Send(
state =>
{
more = enumerator.MoveNext();
}
, null);
}
else
{
enumerator.MoveNext();
}
}
}).ContinueWith(
(task) =>
{
if (!tcs.Task.IsCompleted)
{
tcs.SetResult(default(T));
}
});
return tcs.Task;
}
}
The whole bit about the TaskCompletionSource was my attempt at replicating the way await can "return" a value. The problem is that the coroutine has to actually return an IEnumerable since it is nothing more than a hacked iterator. So I needed to come up with an alternate mechanism to capture a return value.
There are some glaring limitations with this, but I hope this gives you the general idea. It also demonstrates how the CLR could have one generalized mechanism for implementing coroutines for which await and yield return would use ubiquitously, but in different ways to provide their respective semantics.
await always involves the same kind of transformation - but it's a pretty painful one. The library side of await isn't too complicated, but the tricky bit is that the compiler builds a state machine for you, allowing the continuation to jump back to the right place.
It's possible that my some hacky use of iterator blocks (yield return) you could fake something similar... but it would be pretty ugly.
I gave a DevExpress webinar on what the compiler is doing behind the scenes a few weeks ago - that shows decompiled code from a couple of examples, as well as explaining how the compiler builds a task to return, and what the "awaiter" has to do. It may be useful to you.
There are few implementations and examples of coroutines made out of iterators (yield).
One of the examples is Caliburn.Micro framework, that uses this patter for asynchronous GUI operations. But it can easily be generalised for general async code.
The MindTouch DReAM framework implements Coroutines on top of the Iterator pattern which is functionally very similar to Async/Await:
async Task Foo() {
await SomeAsyncCall();
}
vs.
IYield Result Foo() {
yield return SomeAsyncCall();
}
Result is DReAM's version of Task. The framework dlls work with .NET 2.0+, but to build it you need 3.5, since we're using a lot of 3.5 syntax these days.
Bill Wagner from Microsoft wrote an article in MSDN Magazine about how you can use the Task Parallel Library in Visual Studio 2010 to implement async like behavior without adding a dependency on the async ctp.
It uses Task and Task<T> extensively which also has the added benefit that once C# 5 is out, your code will be well prepared to start using async and await.
From my reading, the major differences between yield return and await is that await can provide explicitly return a new value into the continuation.
SomeValue someValue = await GetMeSomeValue();
whereas with yield return, you'd have to accomplish the same thing by reference.
var asyncOperationHandle = GetMeSomeValueRequest();
yield return asyncOperationHandle;
var someValue = (SomeValue)asyncOperationHandle.Result;