I'm running in circles with this one. I have some tasks on an HttpClient (.NET 4 with httpclient package from NuGet), in one of them i'm trying to assign a value to a variable that i declared OUTSIDE the task, at the beggining of the function, but when the execution gets to that point, the variable lost the assigned value and came back to the initial value, like it never changed. But I'm pretty sure it DID change at a moment, when the execution passed through the task.
I've made this screenshot to show it more easily:
What should I do to make my xmlString KEEP the value that was assigned to it inside the task, and use it OUTSIDE the task???
Thanks in advance for your help guys.
Judging by your screenshot (it would be better if you provided the code in your question as well) you are never awaiting your task. Therefore, your last usage where you obtain the value of xmlString happens before your task has finished executing, and presumably before your .ContinueWith() has assigned the variable.
Ideally, your enclosing method should be async as well. Then you can simply await it. Otherwise, you can try calling the .ContinueWith(...).Wait() method first, though at that point your'e not leveraging async semantics at all.
Why don't you use await? It makes the code a lot cleaner.
Replace the client.GetAsync() line with the following:
HttpResponse resp = await client.GetAsync(par);
And then add the try-catch part of the Task. Then it should work as you originally intended it to!
EDIT:
Servy is half-right in the comments. Apart from the Microsoft.Net.HttpClient you will most probably need to manually add Microsoft.Bcl.Async too.
Related
I have a simple async method with the signature:
public async Task<bool> AllowAccessAsync(string authenticatedUserToken)
When calling this method, I appear to have two options when assigning its result to a local variable:
bool response = null;
// option 1
await this.transportService.AllowAccessAsync(authenticatedUserToken).ContinueWith(task => response = task.Result);
// option 2
response = await this.transportService.AllowAccessAsync(authenticatedUserToken);
The first uses a continuation delegate to assign to the local variable, the second assigns the result directly to the variable.
Do these have the same result? Are there any advantages to either approach? Is there a better way to do this?
Do these have the same result?
Edit:
#Servy points out correctly that since the ContinueWith is simply a projection of the result. This means that both operations are semantically equivalent, but exception wise they'll behave differently.
Are there any advantages to either approach? Is there a better way to do this?
Edit 2:
The below remark relate to the use of async-await vs ContinueWith, generally. Looking specifically at both examples as they both use async-await, definitely use the latter, as both contain state-machine generation, but the latter will propagate an AggregateException in case an exception occurs.
async-await has the minimal overhead of producing a state-machine, while ContinueWith doesn't. On the other hand, using async-await lets you "feel" synchronous while actually being asynchronous, and saves you the verbosity of ContinueWith. I would definitely go with async-await, though I advise you to research the right path of using it, as there can be unexpected pitifuls.
By using async/await with Task Parallel Library's ContinueWith you're mixing patterns unnecessarily. There's a whole host of reasons not to do this unless you have no choice, not least of which is that async/await's SynchronizationContext is not preserved by the default implementation of ContinueWith.
So in short, option 2 is correct.
Do these have the same result?
Yes, both options will eventually set the same result into response. The only difference happens when there's an exception. In the first option The exception thrown will be an AggregateException wrapper over the actual exception while in the second one it will be the actual exception.
Are there any advantages to either approach?
There is absolutely no advantage to use ContinueWith in such a way. The second option has the advantages of having better exception handling and being much simpler to write and read.
Is there a better way to do this?
Not really, this is how you use async-await.
As Servy commented, this wasn't how ContinueWith was meant to be used. The ContinueWith equivalent is to put the rest of the method into the continuation. So instead of this:
public async Task FooAsync()
{
var response = await this.transportService.AllowAccessAsync(authenticatedUserToken);
Console.WriteLine(response);
}
You would do this:
public Task FooAsync()
{
return this.transportService.AllowAccessAsync(authenticatedUserToken).
ContinueWith(task => Console.WriteLine(task.GetAwaiter().GetResult()));
}
This does have some performance advantages as it doesn't need the async-await state machine but it's very complicated to get right.
It has more to do with coding style.
The first style might be useful when you have a large workflow which might want to assign different continuations when executing the promise. However it relies on closures. I would not recommend this usage since it's not always predictable. The ContinueWith should be used when you create workflows and each step relies only on the previous ones, and does not communicate with the outside scope, except by delivering a task that yields the final result (which you would then await).
The second one is useful when you are just interested in the result.
Also ContinueWith allows you to specify a TaskScheduler since the one that comes default with your application might not be the one you want.
More information on TaskScheduler here:
http://blog.stephencleary.com/2015/01/a-tour-of-task-part-7-continuations.html
The last couple of days I've been reading about async/await. Yesterday I found this video on Channel 9 what made wonder about some things. Please consider the slide below.
Aside from the issues Lucian Wischik addresses, I wondered about variable assignment. Say we changed the async void into async Task, and added await before the SendData call. This enables us to get the stream, assign the variable m_GetResponse, wait for two seconds and print it. But what happens to the variable? It could be written by a different thread than it is read. Do we need some sort of a memory barrier here, make the variable volatile, or perhaps something else? Could it still be null when we print it?
In the above example, it is safe to read the m_GetResponse because assignment will happen in same UI thread given that this is being called from UI.
This is because SynchronizationContext will be captured and continued when the async method resumes. So it is the same UI thread which writes the field and reading it. This isn't a problem here. Refer my related answer here
If called from non UI context, there is no guarantee that continuations will be ran in same thread. Usually it will be ran in ThreadPool thread. Given that the field read isn't volatile it is possible that you could get the previous value if necessary barriers are not inserted. But you don't need to worry about it because TPL already does this for you.
From the above link
Yes, TPL includes the appropriate barriers when tasks are queued and
at the beginning/end of task execution so that values are
appropriately made visible
So with TPL, you don't need to worry about memory barriers given that the Tasks are already completed. But if you're creating threads manually(which you shouldn't be doing) and dealing with threads directly --you'll have to insert necessary memory barriers.
Btw, ReadToEnd is a blocking call. I would not call it in UI thread. I'd use ReadToEndAsync instead to make your UI thread free. And I'll not use field here; I'll return the value from async method because every method call is just dependent on the parameter so it makes sense to return the value from the method.
So, your method will become something like the following
private async Task<string> SendDataAsync(string url)
{
var request = WebRequest.Create(url);
using(var response = await request.GetResponseAsync());
using(var reader = new StreamReader(request.GetResponseStream());
return await reader.ReadToEndAsync();
}
But what happens to the variable? It could be written by a different
thread than it is read.
If m_GetResponse is a private field, and this class gets invoked multiple times by different threads, then yes, it is possible for the value to be "dirty" once someone else tries to read it. In order to make it thread-safe, you could lock around it. It seems that the authors intention was to invoke this from the UI thread only, hence him making SendData a private method. In that case, it is safe for m_GetResponse to be a private field, as the continuation of the async method which is responsible for the variable assignment will happen inside the UI message loop.
Could it still be null when we print it?
It could be null if somewhere else in the code, someone sets that variable to null, as it's a class level variable. If you're talking about "could it be that we try to print m_GetResponse before await finishes the state-machine execution, then no. Again, i'm not sure the authors intentions were made around concurrent execution, but rather to show you async-await features.
or perhaps something else?
In order to make it thread safe, you can simply remove the global variable, and return a local variable instead. SendData shouldn't be async void anyway, as it isn't used for event handler delegate assignment like Button1_Click.
You could do it better like this (i'll use HttpClient for simplicity):
public async Task<string> SendDataAsync(string url)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync();
return response.Content.ReadAsStringAsync();
}
Note you should remember that async-await isn't meant to address parallelism, it's more about concurrency and easing the use of naturally async IO operations.
I am starting a task with the following code:
var token = tokenSource.Token;
var taskWithToken = new Task(() =>
new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute(),
token);
In my continue with, I need to know the batchRunId and possibly some other variables listed in the ..., however, it doesn't apepar that this is possible???
taskWithToken.ContinueWith(task =>
{
if (!task.IsCanceled)
return;
//TODO: make sure no more subsequent runs happen
//TODO: sync with source data
}
);
Is there something I am missing? How can I make sure the .ContinueWith executes with access to the values it needs?
First, I'm not even sure if you need continuation in your case. Your code could be simplified into something like:
var taskWithToken = new Task(() =>
{
new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute();
// code from the continuation here
},
token);
But if you do want to use ContinueWith() and you're worried about using it because of the ReSharper warning, then you don't have to. Most of the time, code like this is perfectly fine and you can ignore the warning.
Longer version: when you write a lambda that references something from the enclosing scope (so called closure), the compiler has to generate code for that. How exactly does it do that is an implementation detail, but the current compiler generates a single closure class for all closures inside a single method.
What this means in your case is that the compiler generates a class that contains the locals this (because of _unitOfWork), request and batchRunId (and maybe others that you didn't show). This closure object is shared between the new Task lambda and the ContinueWith() lambda, even though the second lambda doesn't use request or this. And as long as the second lambda is referenced from somewhere, those objects can't be garbage collected, even though they can't be accessed from it.
So, this situation can lead to a memory leak, which I believe is why ReSharper is warning you about it. But in almost all cases, this memory leak either doesn't exist (because the second lambda isn't referenced longer than the first one) or it's very small. So, most of the time, you can safely ignore that warning. But if you get mysterious memory leaks, you should investigate the way you're using lambdas and especially places where you get this warning.
You can create your MyTaskData class to store your data and result and it may as well store MyTaskData PreviousTaskData property (from previous task) creating linked list of results. Create a Task<MyTaskData> inside which, at the end, you return myNewTaskData;. Then ContinueWith<MyTaskData>(...) inside which you can get previous results through Task.Result property.
As for continuation on cancelled Task ContinueWith has a variant with TaskContinuationOptions parameter (MSDN) where you can specify NotOnCanceled
I have a question about how customizable the new async/await keywords and the Task class in C# 4.5 are.
First some background for understanding my problem: I am developing on a framework with the following design:
One thread has a list of "current things to do" (usually around 100 to 200 items) which are stored as an own data structure and hold as a list. It has an Update() function that enumerates the list and look whether some "things" need to execute and does so. Basically its like a big thread sheduler. To simplify things, lets assume the "things to do" are functions that return the boolean true when they are "finished" (and should not be called next Update) and false when the sheduler should call them again next update.
All the "things" must not run concurrently and also must run in this one thread (because of thread static variables)
There are other threads which do other stuff. They are structured in the same way: Big loop that iterates a couple of hundret things to do in a big Update() - function.
Threads can send each other messages, including "remote procedure calls". For these remote calls, the RPC system is returning some kind of future object to the result value. In the other thread, a new "thing to do" is inserted.
A common "thing" to do are just sequences of RPCs chained together. At the moment, the syntax for this "chaining" is very verbose and complicated, since you manually have to check for the completion state of previous RPCs and invoke the next ones etc..
An example:
Future f1, f2;
bool SomeThingToDo() // returns true when "finished"
{
if (f1 == null)
f1 = Remote1.CallF1();
else if (f1.IsComplete && f2 == null)
f2 = Remote2.CallF2();
else if (f2 != null && f2.IsComplete)
return true;
return false;
}
Now this all sound awefull like async and await of C# 5.0 can help me here. I haven't 100% fully understand what it does under the hood (any good references?), but as I get it from some few talks I've watched, it exactly does what I want with this nicely simple code:
async Task SomeThingToDo() // returning task is completed when this is finished.
{
await Remote1.CallF1();
await Remote2.CallF2();
}
But I can't find a way how write my Update() function to make something like this happen. async and await seem to want to use the Task - class which in turn seems to need real threads?
My closest "solution" so far:
The first thread (which is running SomeThingToDo) calls their functions only once and stores the returned task and tests on every Update() whether the task is completed.
Remote1.CallF1 returns a new Task with an empty Action as constructor parameter and remembers the returned task. When F1 is actually finished, it calls RunSynchronously() on the task to mark it as completed.
That seems to me like a pervertion of the task system. And beside, it creates shared memory (the Task's IsComplete boolean) between the two threads which I would like to have replaced with our remote messanging system, if possible.
Finally, it does not solve my problem as it does not work with the await-like SomeThingToDo implementation above. It seems the auto-generated Task objects returned by an async function are completed immediately?
So finally my questions:
Can I hook into async/await to use my own implementations instead of Task<T>?
If that's not possible, can I use Task without anything that relates to "blocking" and "threads"?
Any good reference what exactly happens when I write async and await?
I haven't 100% fully understand what it does under the hood - any good references?
Back when we were designing the feature Mads, Stephen and I wrote some articles at a variety of different levels for MSDN magazine. The links are here:
http://blogs.msdn.com/b/ericlippert/archive/2011/10/03/async-articles.aspx
Start with my article, then Mads's, then Stephen's.
It seems the auto-generated Task objects returned by an async function are completed immediately?
No, they are completed when the code in the method body returns or throws, same as any other code.
Can I hook into async/await to use my own implementations instead of Task<T>?
A method which contains an await must return void, Task or Task<T>. However, the expression that is awaited can return any type so long as you can call GetAwaiter() on it. That need not be a Task.
If that's not possible, can I use Task without anything that relates to "blocking" and "threads"?
Absolutely. A Task just represents work that will complete in the future. Though that work is typically done on another thread, there is no requirement.
To answer your questions:
Can I hook into async/await to use my own implementations instead of Task?
Yes. You can await anything. However, I do not recommend this.
If that's not possible, can I use Task without anything that relates to "blocking" and "threads"?
The Task type represents a future. It does not necessarily "run" on a thread; it can represent the completion of a download, or a timer expiring, etc.
Any good reference what exactly happens when I write async and await?
If you mean as far as code transformations go, this blog post has a nice side-by-side. It's not 100% accurate in its details, but it's enough to write a simple custom awaiter.
If you really want to twist async to do your bidding, Jon Skeet's eduasync series is the best resource. However, I seriously do not recommend you do this in production.
You may find my async/await intro helpful as an introduction to the async concepts and recommended ways to use them. The official MSDN documentation is also unusually good.
I did write the AsyncContext and AsyncContextThread classes that may work for your situation; they define a single-threaded context for async/await methods. You can queue work (or send messages) to an AsyncContextThread by using its Factory property.
Can I hook into async/await to use my own implementations instead of Task?
Yes.
If that's not possible, can I use Task without anything that relates to "blocking" and "threads"?
Yes.
Any good reference what exactly happens when I write async and await?
Yes.
I would discourage you from asking yes/no questions. You probably don't just want yes/no answers.
async and await seem to want to use the Task - class which in turn seems to need real threads?
Nope, that's not true. A Task represents something that can be completed at some point in the future, possibly with a result. It's sometimes the result of some computation in another thread, but it doesn't need to be. It can be anything that is happening at some point in the future. For example, it could be the result of an IO operation.
Remote1.CallF1 returns a new Task with an empty Action as constructor parameter and remembers the returned task. When F1 is actually finished, it calls RunSynchronously() on the task to mark it as completed.
So what you're missing here is the TaskCompletionSource class. With that missing puzzle piece a lot should fit into place. You can create the TCS object, pass the Task from it's Task property around to...whomever, and then use the SetResult property to signal it's completion. Doing this doesn't result in the creation of any additional threads, or use the thread pool.
Note that if you don't have a result and just want a Task instead of a Task<T> then just use a TaskCompletionSource<bool> or something along those lines and then SetResult(false) or whatever is appropriate. By casting the Task<bool> to a Task you can hide that implementation from the public API.
That should also provide the "How" variations of the first two questions that you asked instead of the "can I" versions you asked. You can use a TaskCompletionSource to generate a task that is completed whenever you say it is, using whatever asynchronous construct you want, which may or may not involve the use of additional threads.
There is a method which gets a server response with
var response = (HttpWebResponse)await request.GetResponseAsync();
There's additional code to set up the request. I wrapped this in an async method. This method takes a url as parameter. The call for this method is wrapped with a method again, which constructs the actual url.
Imagine the final methodcall looks like this:
string resultString = await GetResultString(parameter);
Then the following problem occured: I want to send multiple requests at the same time. I've got a list of parameters. I did it like this:
var tasks = new List<Task<string>>();
foreach(parameter in parameters)
{
tasks.Add(GetResultString(parameter));
}
List<string> resultStrings = await TaskEx.WhenAll(tasks);
That also works fine. But the number of requests is variable. So it could be 10 requests. But it's also possible that you fire 10.000 requests or even 100.000. So I thought about monitoring the progress in a progress bar. But how could I do this? I already had a look on this piece of code but I can't get any idea of how I could use that for my code. I need to raise an event, everytime a task has finished. But how when there is not any callback when a task finished?
Thanks and regards
PS: could somebody tell me how to use copy & paste for code without putting four spaces in front of every single line of code? I couldn't get any help out of the advanced help. I just can't get it work. And I'm sorry that my English is not too perfect. I'm German. :-)
Well, First you have to ask yourself what you want. If you have 10,000 requests, and you are able to actually get them to await properly, then they're all in progress. In this particular case, you don't know how done each task is, just how many tasks are completed.
If you have 5 tasks, then a progress time line might look like this:
0------------------------------------------1-23-4---5
Do you want it to say 1 / 5 completed? It seem like 1/5 is misleading, because you're probably almost done?
But other than that, the link you mentioned should cover what it is you want. Why didn't it work?
#McKay and craig1231: you were right. The code I provided in the link was perfectly fine, except that an old AsyncCtpLib is used there (well, the post was released at the end of 2010). The code needed to get reworked a bit. But I solved this even before asking this question here.
My problem just was that I didn't understand when the ProgressChangedEvent gets raised.
Basically, when you instantiate this class [Progress<T>, not EventProgress<T> since the new AsyncCtpLib releases], it captures the current
thread's SynchronizationContext. Then, each time Report is called from
inside the TAP method, it raises the ProgressChanged event on the
right thread.
The answer was right there. But thanks, anyway. :)