I have got the code that using WCF, requests data from the server.
For Example:
public static Company LoadCompanyInfo(Guid session)
{
var client = new QualerServiceClient("QualerService");
return client.GetCompanyInfo(session);
}
I need to make my wpf application to run these code asynchronously.
I try:
public static Company LoadCompanyInfoAsync(Guid session)
{
var client = new QualerServiceClient("QualerService");
client.BeginGetCompanyInfo(session, new AsyncCallback(EndLoadCompanyInfoAsync), client);
// How to Get Data from AsyncCallback function?
return null;
}
private static void EndLoadCompanyInfoAsync(IAsyncResult r)
{
var client = r.AsyncState as QualerServiceClient;
var result = client.EndGetCompanyInfo(r);
// how to return the result value ??
}
But I don't know how to return data from callback function.
I have got methods:
BeginGetCompanyInfo and EndGetCompanyInfo
GetCompanyInfoAsync
and event:
GetCompanyInfoCompleted.
Quastions:
How can I get the data from the callback method?
What is the difference between GetCompanyInfoAsync and Begin\End?
Best Practices: How can execute a method asynchronously, so that the GUI of my WPF App is not freezes?
I'm assuming that you're using VS2012.
First, if your target is .NET 4.0, then install (via NuGet) the Async Targeting pack. If your target is .NET 4.5, you don't have to do anything special.
Next, re-create your client proxy. The existing Begin/End/Async endpoints will be replaced by a single Task<Company> GetCompanyInfoAsync(Guid).
Now you can use it like this:
public static Task<Company> LoadCompanyInfoAsync(Guid session)
{
var client = new QualerServiceClient("QualerService");
return client.GetCompanyInfoAsync(session);
}
public async void ButtonClickOrWhatever(...)
{
var company = await LoadCompanyInfoAsync(mySession);
// Update UI with company info.
}
The old Begin/End method pair was using the Asynchronous Programming Model (APM). The old Async/event pair was using the Event-based Asynchronous Programming model (EAP). The new Async method is using the Task-based Asynchronous Programming model (TAP). I have more information on async WCF on my blog.
You could use the async CTP for .net 4, which will become part of .net in 5.
It adds two new keywords into C# the async and await keywords.
You mark a method or lamda with the async keyword and return a
Task or Task<T>
when you call your method you would call it like so
var result = await LoadCompanyInfo(sessionId);
Async CTP
public static async Task<Company> LoadCompanyInfo(Guid session)
{
Company result = default(Company);
await TaskEx.Run(()=>{
var client = new QualerServiceClient("QualerService");
result = client.GetCompanyInfo(session);
});
return result;
}
Use TPL:
Task t = TaskFactory.FromAsync(
beginMethod: BeginGetCompanyInfo,
endMethod: EndGetCompanyInfo,
arg1: session,
state: null);
t.ContinueWith(result =>
{
// handle result
});
Related
In a .NET Core asp.net web application I'm building, tasks are initiated in a request; in certain scenarios, we want to await the completion of this task in another request.
To accomplish this, I've put in place a static dictionary that stores references to these tasks:
public static volatile Dictionary<int, Task> MyTasks = new Dictionary<int, Task>();
Running tasks are awaited, if necessary, from separate requests:
public static async Task GenerateMyData(int itemId, SomeOtherData data)
{
var curTask = MyTasks.Get(itemId); //<- extension method wrapper for TryGetValue
if (curTask != null && !curTask.IsCompleted)
{
await curTask;
}
var newTask = Task.Run(async () =>
{
AddPrimaryData(itemId, data);
await AddImageData(itemId, data);
MyTasks[itemId] = null;
});
MyTasks[itemId] = newTask;
}
While it works in my development environment and as web-app under a light load, the more I read about async/await the more unsure I am if this will function as expected under a heavier load. Does this method appear to be safe for an asp.net core 2.1 web app?
It's better to use the thread-safe ConcurrentDictionary<TKey,TValue> Class. Making a classic collection volatile alone doesn't make it thread-safe. You would have to enclose all the operations in a lock statement.
You add items with (ConcurrentDictionary<TKey,TValue> Class)
bool success = dict.TryAdd(itemId, data);
And retrieve them with
bool success = dict.TryGetValue(itemId, out data);
There are also methods like TryRemove and TryUpdate.
I'm using the Gcm Network Manager to schedule tasks, in one of those tasks I need to perform an HTTP request. Until now it was written with HttpWebRequest so nothing was async.
Now I would like to reuse code that is written with HttpClient and is async.
The problem that arrises is that I cannot make the OnRunTask() async as it needs to return an int:
e.g.
public override int OnRunTask(TaskParams #params)
{
var result = await performSync();
if(result)
{
return GcmNetworkManager.ResultSuccess;
}
return GcmNetworkManager.ResultReschedule;
}
What could I do to be able to reuse async code here ?
You can use Task.Run inside your OnRunTask method like this :
Task.Run( async () =>
{
// Do your stuff here
await asyncTask();
});
You will no need to have OnRunTask async with this technique
Hope it helps
Edit
If you need the return value to match the framework / library signature, you can also use .Result
E.g.
var result = asyncTask().Result;
...
This question already has answers here:
How to call asynchronous method from synchronous method in C#?
(17 answers)
Closed 6 years ago.
I have the below method:
public string RetrieveHolidayDatesFromSource() {
var result = this.RetrieveHolidayDatesFromSourceAsync();
/** Do stuff **/
var returnedResult = this.TransformResults(result.Result); /** Where result gets used **/
return returnedResult;
}
private async Task<string> RetrieveHolidayDatesFromSourceAsync() {
using (var httpClient = new HttpClient()) {
var json = await httpClient.GetStringAsync(SourceURI);
return json;
}
}
The above does not work and seems to not return any results properly. I am not sure where I am missing a statement to force the await of a result? I want the RetrieveHolidayDatesFromSource() method to return a string.
The below works fine but it is synchronous and I believe it can be improved upon? Note that the below is synchronous in which I would like to change to Asynchronous but am unable to wrap my head around for some reason.
public string RetrieveHolidayDatesFromSource() {
var result = this.RetrieveHolidayDatesFromSourceAsync();
/** Do Stuff **/
var returnedResult = this.TransformResults(result); /** This is where Result is actually used**/
return returnedResult;
}
private string RetrieveHolidayDatesFromSourceAsync() {
using (var httpClient = new HttpClient()) {
var json = httpClient.GetStringAsync(SourceURI);
return json.Result;
}
}
Am I missing something?
Note: For some reason, when I breakpoint the above Async Method, when it gets to the line var json = await httpClient.GetStringAsync(SourceURI) it just goes out of breakpoint and I can't go back into the method.
Am I missing something?
Yes. Asynchronous code - by its nature - implies that the current thread is not used while the operation is in progress. Synchronous code - by its nature - implies that the current thread is blocked while the operation is in progress. This is why calling asynchronous code from synchronous code literally doesn't even make sense. In fact, as I describe on my blog, a naive approach (using Result/Wait) can easily result in deadlocks.
The first thing to consider is: should my API be synchronous or asynchronous? If it deals with I/O (as in this example), it should be asynchronous. So, this would be a more appropriate design:
public async Task<string> RetrieveHolidayDatesFromSourceAsync() {
var result = await this.DoRetrieveHolidayDatesFromSourceAsync();
/** Do stuff **/
var returnedResult = this.TransformResults(result); /** Where result gets used **/
return returnedResult;
}
As I describe in my async best practices article, you should go "async all the way". If you don't, you won't get any benefit out of async anyway, so why bother?
But let's say that you're interested in eventually going async, but right now you can't change everything, you just want to change part of your app. That's a pretty common situation.
In that case, the proper approach is to expose both synchronous and asynchronous APIs. Eventually, after all the other code is upgraded, the synchronous APIs can be removed. I explore a variety of options for this kind of scenario in my article on brownfield async development; my personal favorite is the "bool parameter hack", which would look like this:
public string RetrieveHolidayDatesFromSource() {
return this.DoRetrieveHolidayDatesFromSourceAsync(sync: true).GetAwaiter().GetResult();
}
public Task<string> RetrieveHolidayDatesFromSourceAsync() {
return this.DoRetrieveHolidayDatesFromSourceAsync(sync: false);
}
private async Task<string> DoRetrieveHolidayDatesFromSourceAsync(bool sync) {
var result = await this.GetHolidayDatesAsync(sync);
/** Do stuff **/
var returnedResult = this.TransformResults(result);
return returnedResult;
}
private async Task<string> GetHolidayDatesAsync(bool sync) {
using (var client = new WebClient()) {
return sync
? client.DownloadString(SourceURI)
: await client.DownloadStringTaskAsync(SourceURI);
}
}
This approach avoids code duplication and also avoids any deadlock or reentrancy problems common with other "sync-over-async" antipattern solutions.
Note that I would still treat the resulting code as an "intermediate step" on the path to a properly-asynchronous API. In particular, the inner code had to fall back on WebClient (which supports both sync and async) instead of the preferred HttpClient (which only supports async). Once all the calling code is changed to use RetrieveHolidayDatesFromSourceAsync and not RetrieveHolidayDatesFromSource, then I'd revisit this and remove all the tech debt, changing it to use HttpClient and be async-only.
public string RetrieveHolidayDatesFromSource() {
var result = this.RetrieveHolidayDatesFromSourceAsync().Result;
/** Do stuff **/
var returnedResult = this.TransformResults(result.Result); /** Where result gets used **/
return returnedResult;
}
If you add .Result to the async call, it will execute and wait for the result to arrive, forcing it to be synchronous
UPDATE:
private static string stringTest()
{
return getStringAsync().Result;
}
private static async Task<string> getStringAsync()
{
return await Task.FromResult<string>("Hello");
}
static void Main(string[] args)
{
Console.WriteLine(stringTest());
}
To address the comment: This works without any problems.
I have a class library that (amongst other things) acts as a wrapper for an external client library for a web API.
My (simplified) code here takes a query string, generates a ReportUtilities object, uses this to download a report, then returns the report string back to the caller:
public string GetXmlReport(string queryString)
{
ReportUtilities reportUtil = new ReportUtilities(_user,queryString,"XML");
byte[] data = reportUtil.GetResponse().Download();
return Encoding.UTF8.GetString(data);
}
The issue is that this method is downloading data from a webservice using a syncronous method. I would like to make this available asyncronously in my library by adding a GetXmlReportAsync() method to my class.
Now, this would be straighforward if the ReportUtilities class provided a GenerateAndDownloadAsync() method returning Task<byte[]> but unfortunately it does not and it is in the external library so I am stuck with what it provides.
The ReportUtilities class does have a GetResponseAsync() method that returns void and provides a delegate for a a OnReadyCallback method together with an OnReadyCallback OnReady{get;set;} property.
I should add that .GetResponse() returns a ReportResponse object which does have a DownloadAsync() method but, again, this returns void rather than Task<byte[]>. Again ReportResponse comes with OnDownloadSuccessCallback delegate and OnDownloadSuccessCallback OnDownloadSuccess { get; set; } property.
It's almost as if the external library authors are 'rolling thier own' async API rather than using the one built into C#?
My question is: How can I implement a GetXmlReportAsync() method in my class to make the most efficient use of the asyncronous functions in the client library?
Obviously I could just do:
public async Task<string> GetXmlReportAsync(string queryString)
{
ReportUtilities reportUtil = new ReportUtilities(_user,queryString,"XML");
byte[] data = await Task.Run(() => { return reportUtil.GetResponse().Download(); });
return Encoding.UTF8.GetString(data);
}
but then the thread gets tied up with 2 syncronous input/output method calls to the external library: .GetResponse() and .Download() which surely isnt optimal?
Alternatively, I could imagine a situation where I just exposed a similar API to the external library in my own with clients having to provide callbacks for when thier reports are ready but I would much prefer to wrap this up into the more familiar async/await style API.
Am I trying to fit a square peg in a round hole or am I missing a neat way to wrap this into an async/await style API?
It's almost as if the external library authors are 'rolling thier own' async API rather than using the one built into C#?
A not uncommon situation for older libraries, particularly ones that were directly ported from other platforms/languages.
Am I trying to fit a square peg in a round hole or am I missing a neat way to wrap this into an async/await style API?
The pattern they're using is very similar to EAP, and there's a common pattern for converting EAP to TAP. You can do something similar with a few adjustments.
I recommend creating extension methods for the third-party library types that give you nice TAP endpoints, and then building your logic on top of that. That way, the TAP method doesn't mix concerns (translating asynchronous patterns, and doing business logic - i.e., converting to a string).
The ReportUtilities class does have a GetResponseAsync() method that returns void and provides a delegate for a a OnReadyCallback method together with an OnReadyCallback OnReady{get;set;} property.
Something like this, then:
public static Task<ReportResponse> GetResponseTaskAsync(this ReportUtilities #this)
{
var tcs = new TaskCompletionSource<ReportResponse>();
#this.OnReady = response =>
{
// TODO: check for errors, and call tcs.TrySetException if one is found.
tcs.TrySetResult(response);
};
#this.GetResponseAsync();
return tcs.Task;
}
Similarly for the next level:
public static Task<byte[]> DownloadTaskAsync(this ReportResponse #this)
{
var tcs = new TaskCompletionSource<byte[]>();
// TODO: how to get errors? Is there an OnDownloadFailed?
#this.OnDownloadSuccess = result =>
{
tcs.TrySetResult(result);
};
#this.DownloadAsync();
return tcs.Task;
}
Then your business logic can use the clean TAP endpoints:
public async Task<string> GetXmlReportAsync(string queryString)
{
ReportUtilities reportUtil = new ReportUtilities(_user, queryString, "XML");
var response = await reportUtil.GetResponseTaskAsync().ConfigureAwait(false);
var data = await response.DownloadTaskAsync().ConfigureAwait(false);
return Encoding.UTF8.GetString(data);
}
How can I implement a GetXmlReportAsync() method in my class to make
the most efficient use of the asyncronous functions in the client
library?
You could wrap the asynchoronous GetResponseAsync call with a TaskCompletionSource<string>. It would register the delegate once complete and set the completion of the task via SetResult. It would look something of this sort:
public Task<string> GetXmlReportAsync()
{
var tcs = new TaskCompletionSource<string>();
ReportUtilities reportUtil = new ReportUtilities(_user,queryString,"XML");
reportUtil.GetResponseAsync(callBack =>
{
// I persume this would be the callback invoked once the download is done
// Note, I am assuming sort sort of "Result" property provided by the callback,
// Change this to the actual property
byte[] data = callBack.Result;
tcs.SetResult(Encoding.UTF8.GetString(data));
});
return tcs.Task;
}
My OperationContract:
public List<MessageDTO> GetMessages()
{
List<MessageDTO> messages = new List<MessageDTO>();
foreach (Message m in _context.Messages.ToList())
{
messages.Add(new MessageDTO()
{
MessageID = m.MessageID,
Content = m.Content,
Date = m.Date,
HasAttachments = m.HasAttachments,
MailingListID = (int)m.MailingListID,
SenderID = (int)m.SenderID,
Subject = m.Subject
});
}
return messages;
}
In Service Reference configuration I checked the option "Generate asynchronous operations". How do I use the generated GetMessagesAsync()? In the net I found examples that use AsyncCallback, however I'm not familiar with that. Is there a way to use it in some friendly way like async and await keywords in .NET 4.5? If not, what should I do to invoke the method asynchronously?
If you select 'Generate asynchrounous operations', you will get the 'old' behavior where you have to use callbacks.
If you want to use the new async/await syntax, you will have to select 'Generate task-based operations' (which is selected by default).
When using the default Wcf template, this will generate the following proxy code:
public System.Threading.Tasks.Task<string> GetDataAsync(int value) {
return base.Channel.GetDataAsync(value);
}
As you can see, there are no more callbacks. Instead a Task<T> is returned.
You can use this proxy in the following way:
public static async Task Foo()
{
using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client())
{
Task<string> t = client.GetDataAsync(1);
string result = await t;
}
}
You should mark the calling method with async and then use await when calling your service method.
Your Service Reference can (if you are using .Net 4.5) be set to generate task-based async calls. (Configure Service Reference > check Allow generation of asynchronous operations > select Generate task-based operations) These can be used like any async method. Here's an example of how to use it:
using (var proxy = new YourServiceClient())
{
var t1 = proxy.GetMessagesAsync();
var t2 = proxy.GetMessagesAsync();
//they're runnning asynchronously now!
//let's wait for the results:
Task.WaitAll(t1, t2);
var result1 = t1.Result;
var result2 = t2.Result;
Console.WriteLine(result1);
Console.WriteLine(result2);
}
If your client is not using .Net 4.5, you cannot generate service references that use async. You'll have to do it the old fashioned way, using callbacks. Here's an example:
static void m()
{
var proxy = new YourServiceClient();
proxy.GetMessagesCompleted += proxy_GetMessagesCompleted;
proxy.GetMessagesAsync();
}
static void proxy_GetMessagesCompleted(object sender, GetMessagesCompletedEventArgs e)
{
var proxy = (IDisposable)sender;
proxy.Dispose(); //actual code to close properly is more complex
if (e.Error != null)
{
// do something about this
}
var result = e.Result;
Console.WriteLine(result);
}
Note that in actual code for either of these scenarios, you shouldn't use using or IDisposable.Dispose() to clean up the client, see Avoiding Problems with the Using Statement and this code to get you started into the confusing world of closing these things.
If you're on VS2012, then you can use the *Async calls like this:
var proxy = new MyClient();
var result = await proxy.GetMessagesAsync();
How about something like this...
public async Task<string> DoSomething()
{
var someProxy = new ServiceClient();
var t = someProxy.SomeMethodAsync();
await Task.WhenAny(t);
return t.Result;
}