I have a method that I use to get string from web service
I started the code with
var task = _tempClient.GetteststringAsync();
string teststring = await task;
but I noticed that the code not wait till the call end and the value retrieved ,so I tried something like
string teststring= string.Empty;
var t1 = Task.Factory.StartNew(new Func<Task>(async () => teststring= await _tempClient.GetteststringAsync()))
.Unwrap();
t1.Wait();
but this cause the application stuck , any idea how to make it work ,tempClient is a service refrence object . I use it to intialise the webrefrence in MVC Application, it's the helper class
Your first attempt was much closer to doing the right thing, calling task.Wait() or task.Result is a blocking call and can often cause a deadlock. Have a look at this article for async/await best practices.
What you want to do is what you had first:
var task = _tempClient.GetteststringAsync();
string teststring = await task;
Calling _tempClient.GetteststringAsync() will start executing on a thread pool thread and once finished the result will be returned into teststring and the rest of the method will execute on the original request thread. At that point you just need to do whatever you need to with teststring.
I solved it using
http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx using this code looks like
AsyncPump.Run(async delegate
{
await DemoAsync();
});
Related
I need to get the returned value without await operator(in below sample I need to get the "hello world" in var y without await operator). Because one method is referred to a lot of places.But my requirement is that method is executed at asynchronously for particular operations. None other time it is enough to be executed as synchronously.
If I put await in all referred places that method needs to change as async and also referred methods need to change as async and await.
Is there any possibility to get the returned value?
Please find below sample code snippet:
class Program
{
static void Main(string[] args)
{
var x = getString();
}
public static async Task<string> getString()
{
var y = await GetString2();
return y;
}
public static async Task<string> GetString2()
{
return "hello world";
}
}
Here is there any possibility to get "hello world" string in var y without await operator?
Are you looking for something like that;
var str = GetString2().Result;
Result blocks the calling thread until the asynchronous operation is complete; it is equivalent the Wait method. await has asynchronous wait for the task completion.
Also, as #Sir Rufo and #MistyK described, you will get AggregateException on a possible exception, so it would be better to use GetAwaiter like this;
var str = GetString2().GetAwaiter().GetResult();
I wouldn't use Result because If error is thrown, you'll get AggregateException. It's better to do this:
var str = GetString2().GetAwaiter().GetResult()
You have one of two options:
Either use the Result property of the task. This has the downside that it can block the message pump and cause problems. In a console app this might work, but you need to test.
GetString2().Result;
Use the ContinueWith method to pass an action to perform when the task is complete. The disadvantage being you will not have access to the data immediately, and the calling function will return.
GetString2().ContinueWith(result => Console.WriteLine(result));
I need to get the returned value without await operator(in below sample I need to get the "hello world" in var y without await operator). Because one method is referred to a lot of places.But my requirement is that method is executed at asynchronously for particular operations. None other time it is enough to be executed as synchronously.
If I put await in all referred places that method needs to change as async and also referred methods need to change as async and await.
Is there any possibility to get the returned value?
Please find below sample code snippet:
class Program
{
static void Main(string[] args)
{
var x = getString();
}
public static async Task<string> getString()
{
var y = await GetString2();
return y;
}
public static async Task<string> GetString2()
{
return "hello world";
}
}
Here is there any possibility to get "hello world" string in var y without await operator?
Are you looking for something like that;
var str = GetString2().Result;
Result blocks the calling thread until the asynchronous operation is complete; it is equivalent the Wait method. await has asynchronous wait for the task completion.
Also, as #Sir Rufo and #MistyK described, you will get AggregateException on a possible exception, so it would be better to use GetAwaiter like this;
var str = GetString2().GetAwaiter().GetResult();
I wouldn't use Result because If error is thrown, you'll get AggregateException. It's better to do this:
var str = GetString2().GetAwaiter().GetResult()
You have one of two options:
Either use the Result property of the task. This has the downside that it can block the message pump and cause problems. In a console app this might work, but you need to test.
GetString2().Result;
Use the ContinueWith method to pass an action to perform when the task is complete. The disadvantage being you will not have access to the data immediately, and the calling function will return.
GetString2().ContinueWith(result => Console.WriteLine(result));
I have an async codeblock running on the pageload.
The codes run smoothy until you reach capturevalue method where we create a new task.On executing that code block the await just freezes and then the control doesnt come back seems like the code just went to deadlock
protected void Page_Load(object sender, EventArgs e)
{
try
{
var textvalue = GetTextValueFromTask();
txtbox.Text = textvalue.Result;
string ss = "";
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private async Task<string> GetTextValueFromTask()
{
string strReturn = await CaptureValue();
return strReturn;
}
private async Task<string> CaptureValue()
{
Thread.Sleep(5000);
Task<string> T = Task.Factory.StartNew<string>(() => "hi");
return await T;
}
Then I made a small change in Capturevalue method.
private async Task<string> CaptureValue()
{
Thread.Sleep(5000);
Task<string> T = Task.Factory.StartNew<string>(() => "hi");
string ss = T.Result;
return await T;
}
Once I made that change it started working normal.What difference did it make on just fetching the result initially. Please help me Iam a newbee to async
The difference is that second time it doesn't happen any "await" because you waited the task yourself, so await doesn't do anything.
I think you missed the await keyword the first time, here:
var textvalue = await GetTextValueFromTask();
Without it your method GetTextValueFromTask runs synchronously, then it comes into CaptureValue method where await occurs. But the default behaviour of the await is that it tries to capture synchronization context where it was called and to continue the rest of the method in that context, in your example it is WPF synchronization context, which does not allow more than one thread to execute at once. But the continuation cannot proceed, because context is already used by await mechanism.
So, one more time. There is one thread (UI thread), that executes your code up to the last await, which is return await T;, then it yields back to the caller - GetTextValueFromTask, and again to the Page_Load when it gets blocked, because initially you called GetTextValueFromTask synchronously (without await). After that, your operation T completes, and your code tries to continue executing using the initial synchronization context, the WPF one. But it can't, because it is already waiting in the Page_Load.
The link in the comments describes the situation in more detail.
Also consider not using Thread.Sleep in async/await scenarios, because it kills all the "asynchronous" nature of the code. Further reading: link.
Another general piece of advice, which is not directly applicable to your source code, is not to use Task.Factory.StartNew, but rather use Task.Run. Explanation here.
Please use Task.Run() instead of Task.Factory.StartNew()
var T = Task.Run(() => "hi");
It's up to Task.Run to decide how to handle this task.
Also please use .ConfigureAwait(false) in your await calls that do not requires the continuation being done in the awaiter thread context.
I'm working on a C# console application that will be responsible for running an array of tasks. The basic structure for that is as follows:
var tasks = workItems.Select(x => Task.Factory.StartNew(() =>
{
DoSomeWork(x);
})).ToArray();
Task.WaitAll(tasks);
The problem is that DoSomeWork() is an async method which awaits the result of another task, which also needs to await a call to the Facebook API.
http://facebooksdk.net/docs/reference/SDK/Facebook.FacebookClient.html#GetTaskAsync(string)
public async void DoSomeWork(WorkItem item)
{
var results = await GetWorkData();
}
public async Task<List<WorkData>> GetWorkData()
{
var fbClient = new FacebookClient();
var task = fbClient.GetTaskAsync("something");
var fbResults = await task;
};
I thought I would be able to support this notion of nested tasks with the call to Task.WaitAll() but the execution of the parent tasks finishes almost immediately. Putting a Console.ReadLine() at the end of the application to prevent it from early execution shows that the result will indeed come back later from Facebook.
Am I missing something obvious or is there a better way to block for my Task collection that will allow for this kind of scenario?
DoSomeWork needs to not return void. The by not returning a Task the caller has no way of knowing when if finishes.
Additionally, it's already asynchronous, so there is no reason to use StartNew here. Just call DoSomeWork directly, since it should be returning a Task.
I want to use the BeginGetResponse method in order to call many URLs which I hold on a list.
I have 2 questions on how to implement this:
according to the example in http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.95).aspx
we use:
public static ManualResetEvent allDone= new ManualResetEvent(false);
is that wise to use a static member in web application since it's shared with other threads ? can this cause for problems ?
how can I tell when all the callbacks were finished ? I need to do a summary report on the results
Thanks
While you can use an event, I'd recommend using Task<T> and the FromAsync method on the TaskFactory class like so:
// Execution of tasks starts here because of the
// call to ToArray.
Task<WebResponse>[] tasks = uris.Select(u => {
// Create the request.
WebRequest req = ...;
// Make the call to return the response asynchronously with
// a Task.
return Task.Factory.FromAsync(req.BeginGetResponse,
req.EndGetResponse, null);
}).ToArray();
Once you have that, you can easily wait on all of the Task<T> instances using the ContinueWhenAll method on the TaskFactory class like so with a continuation:
Task.Factory.ContinueWhenAll(tasks, t => {
// Note that t is an array of Task, so you have to cast
// each element to a Task<WebRequest>.
// Process all of them here.
});
Note the above returns a Task which you will have to wait on or continued on when done (if your're concerned about the notification).
If you are using .NET 4.5, you don't need to use the ContinueWhenAll method on the TaskFactory class, but can use the WhenAll method on the Task class to perform the work:
// Note that work does not start here yet because of deferred execution.
// If you want it to start here, you can call ToArray like above.
IEnumerable<Task<WebResponse>> tasks = uris.Select(u => {
// Create the request.
WebRequest req = ...;
// Make the call to return the response asynchronously with
// a Task.
return Task.Factory.FromAsync(req.BeginGetResponse,
req.EndGetResponse, null);
});
// Execution will start at this call:
Task<Task<WebRequest>[]> allTasks = Task.WhenAll(tasks);
// Continue or wait here.
Note that the above was before it was revealed that .NET 3.5 was being used.
If you want to wait in main thread for completition, then this solution is not very good. First request will change event's state to "set". Therefore, main thread will continue execution after the first request completed.
A suggest you to use CountdownEvent:
using(var countdownEvent = new CountdownEvent(list.Count))
{
// launch requests with countdownEvent.Signal(); in the end
countdownEvent.Wait();
}
You must store reference to countdownEvent inside RequestState. Also, don't forget to control timeouts - start new thread with ThreadPool.RegisterWaitForSingleObject.
I guess you're trying to do something like this:
int total = urls.Count;
ManualResetEvent evt = new ManualResetEvent();
ConcurrentBag<WebResponses> responses = new ConcurrentBag<WebResponse>();
foreach(Uri in uri)
{
HttpWebRequest req = ...;
req.BeginGetResponse(res=>
{
WebResponse res = req.EndGetResponse();
// do what you need with the response.
// maybe add it to a collection so you can report on it later:
responses.Add(res);
if(Interlocked.Decrement(ref total) == 0)
{
// this was the last response. set event.
evt.Set();
}
}, null);
}
evt.Wait();
foreach(WebResponse res in responses)
{
// report something about the response.
}
Note that an optimal workflow will not need an event. For extra credit, get rid of it all together and move your final logic inside the if that sets the event.
Also, this code is untested and lacks error handling, so be sure to add that in if you play with it at all.