I have created a webservice and a method as follows:
[WebMethod]
public bool GetMasterExit(int RoomID)
{
if(GameList[RoomID][0] == "\0")
return true;
else
return false;
}
And then I call this from WP client using the following way but there is a problem that I want the main process blocked until the webservice returns the value I want but in this way the value is wrong for delay.
I have tried to use the Await but I got an error that "cannot await void", so Anyone knows how to solve this problem?
public void Test()
{
ServiceSoapClient GameClient = new ServiceSoapClient();
GameClient.GetMasterExitCompleted += _clientGetMasterExitCompleted;
GameClient.GetMasterExitAsync(RoomID);
Console.WriteLine(MasterExit);
}
public void _clientGetMasterExitCompleted(object sender, GetMasterExitCompletedEventArgs e)
{
MasterExit = e.Result;
}
I want the main process blocked until the webservice returns the value
This is an incorrect approach. Especially on mobile platforms such as WP, you're not allowed to block the UI like that.
The proper solution is to use await. Follow the Task-based Asynchronous Pattern and write an EAP wrapper called GetMasterExitTaskAsync.
If you are willing to use await then you must add modifier async to your function signature.Hope this helps.
Use async and await like this:
public async void Test()
{
ServiceSoapClient GameClient = new ServiceSoapClient();
GameClient.GetMasterExitCompleted += _clientGetMasterExitCompleted;
await GameClient.GetMasterExitAsync(RoomID);
Console.WriteLine(MasterExit);
}
Related
My async method is as below:
public async Task<List<object>> handleSummaryOfWallets()
{
string token = giveMeToken("URL AND CREDS");
Channel channel = new Channel("NANANANA GIROUD", ChannelCredentials.Insecure);
OMGadminAPI.OMGadminAPIClient client = new OMGadminAPI.OMGadminAPIClient(channel);
var summaryBalancesParams = new OMGadminAPIGetCurrenciesSummariesParams();
summaryBalancesParams.AdminAuthTokenSecret = token;
List<object> summariesCurrenciesOMGadmin = new List<object>();
using (var call = client.GetCurrenciesSummaries(summaryBalancesParams))
{
while (await call.ResponseStream.MoveNext())
{
OMGadminAPICurrencySummary currencySummary = call.ResponseStream.Current;
summariesCurrenciesOMGadmin.Add(currencySummary);
Console.WriteLine(summariesCurrenciesOMGadmin);
}
return summariesCurrenciesOMGadmin;
}
}
As you can see, above async method returns list of objects. I call this method as below:
var listOfBalances = balances.handleSummaryOfWallets().Wait();
and it gives me error:
Error CS0815: Cannot assign void to an implicitly-typed variable
From the error, I understand that this is not correct way to call async method. But I need to read ready list of objects from async fetched data. Its request-response, no real stable stream. So I need to generate this list only once per request. I'm using gRPC framework for RPC calls.
Please help me fetch this data and make ready to use.
The Task.Wait method waits for the Task to complete execution. It returns void. That is the reason why the exception.
Now to overcome the exception and to read the return value, one way is as mentioned in other answer and the comments; await the call as below:
public async void TestAsync()
{
var listOfBalances = await handleSummaryOfWallets();
}
Note that your calling method should also be async method now.
As you are calling Wait in your code, it looks that you want the result immediately; you have nothing else left to do that does not depend on result. In that case, you may choose to stop async chain by calling Wait. But you need to do some changes as below:
public void TestAsync()
{
var task = handleSummaryOfWallets();//Just call the method which will return the Task<List<object>>.
task.Wait();//Call Wait on the task. This will hold the execution until complete execution is done.
var listOfBalances = task.Result;//Task is executed completely. Read the result.
}
Note that calling method is no longer async. Other explanation is given in code-comments.
Other short alternative to above code is as below:
public void TestAsync()
{
var listOfBalances = handleSummaryOfWallets().Result;
}
Just use await while calling your method
var listOfBalances = await balances.handleSummaryOfWallets();
Suppose I have written a library which relies on async methods:
namespace MyLibrary1
{
public class ClassFromMyLibrary1
{
public async Task<string> MethodFromMyLibrary1(string key, Func<string, Task<string>> actionToProcessNewValue)
{
var remoteValue = await GetValueByKey(key).ConfigureAwait(false);
//do some transformations of the value
var newValue = string.Format("Remote-{0}", remoteValue);
var processedValue = await actionToProcessNewValue(newValue).ConfigureAwait(false);
return string.Format("Processed-{0}", processedValue);
}
private async Task<string> GetValueByKey(string key)
{
//simulate time-consuming operation
await Task.Delay(500).ConfigureAwait(false);
return string.Format("ValueFromRemoteLocationBy{0}", key);
}
}
}
I followed the recommendations of using ConfigureAwait(false) (like in this post) everywhere in my library. Then I use it in synchronous way from my test app and get a failure:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button1_OnClick(object sender, RoutedEventArgs e)
{
try
{
var c = new ClassFromMyLibrary1();
var v1 = c.MethodFromMyLibrary1("test1", ActionToProcessNewValue).Result;
Label2.Content = v1;
}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError("{0}", ex);
throw;
}
}
private Task<string> ActionToProcessNewValue(string s)
{
Label1.Content = s;
return Task.FromResult(string.Format("test2{0}", s));
}
}
}
The failure is:
WpfApplication1.vshost.exe Error: 0 :
System.InvalidOperationException: The calling thread cannot access
this object because a different thread owns it. at
System.Windows.Threading.Dispatcher.VerifyAccess() at
System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object
value) at System.Windows.Controls.ContentControl.set_Content(Object
value) at WpfApplication1.MainWindow.ActionToProcessNewValue(String
s) in
C:\dev\tests\4\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:line
56 at
MyLibrary1.ClassFromMyLibrary1.d__0.MoveNext()
in
C:\dev\tests\4\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:line
77
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at WpfApplication1.MainWindow.d__1.MoveNext() in
C:\dev\tests\4\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:line
39 Exception thrown: 'System.InvalidOperationException' in
WpfApplication1.exe
Obviously the error happens because the awaiters in my library discard current WPF context.
From the other hand, after removing the ConfigureAwait(false) everywhere in the library I obviously get a deadlock instead.
There is more detailed example of code which explains some constraints that I have to deal with.
So how can I address this issue? What is the best approach here? Do I still need to follow the best practice regarding ConfigureAwait?
PS, In real scenario I have many classes and methods therefore tons of such async calls in my library. It's nearly impossible to find out if some particular async call requires context or not (see comments to #Alisson response) to fix it. I don't care about performance though, at least at this point. I'm looking for some general approach to address this issue.
Normally a library will document if a callback will be guaranteed to be on the same thread that called it, if it is not documented the safest option will be to assume it does not. Your code example (and the 3rd party you are working with from what I can tell from your comments) fall under the category of "Not guaranteed". In that situation you just need to check if you need to do a Invoke from inside the callback method and do it, you can call Dispatcher.CheckAccess() and it will return false if you need to invoke before using the control.
private async Task<string> ActionToProcessNewValue(string s)
{
//I like to put the work in a delegate so you don't need to type
// the same code for both if checks
Action work = () => Label1.Content = s;
if(Label1.Dispatcher.CheckAccess())
{
work();
}
else
{
var operation = Label1.Dispatcher.InvokeAsync(work, DispatcherPriority.Send);
//We likely don't need .ConfigureAwait(false) because we just proved
// we are not on the UI thread in the if check.
await operation.Task.ConfigureAwait(false);
}
return string.Format("test2{0}", s);
}
Here is a alternate version with a syncronous callback instead of a async one.
private string ActionToProcessNewValue(string s)
{
Action work = () => Label1.Content = s;
if(Label1.Dispatcher.CheckAccess())
{
work();
}
else
{
Label1.Dispatcher.Invoke(work, DispatcherPriority.Send);
}
return string.Format("test2{0}", s);
}
Here is another version if you wanted to get the value from Label1.Content instead of assigning it, this also does not need to use async/await inside the callback.
private Task<string> ActionToProcessNewValue(string s)
{
Func<string> work = () => Label1.Content.ToString();
if(Label1.Dispatcher.CheckAccess())
{
return Task.FromResult(work());
}
else
{
return Label1.Dispatcher.InvokeAsync(work, DispatcherPriority.Send).Task;
}
}
IMPORTANT NOTE: all of these methods will cause your program to deadlock if you don't get rid of the .Result in the button click handler, the Dispatcher.Invoke or the Dispatcher.InvokeAsync in the callback will never start while it is waiting for .Result to return and .Result will never return while it is waiting for the callback to return. You must change the click handler to be async void and do a await instead of the .Result.
Actually, you're receiving a callback in your ClassFromMyLibrary1 and you can't assume what it'll do (like updating a Label). You don't need ConfigureAwait(false) in your class library, as the same link you provided gives us an explanation like this:
As asynchronous GUI applications grow larger, you might find many
small parts of async methods all using the GUI thread as their
context. This can cause sluggishness as responsiveness suffers from
"thousands of paper cuts".
To mitigate this, await the result of ConfigureAwait whenever you can.
By using ConfigureAwait, you enable a small amount of parallelism:
Some asynchronous code can run in parallel with the GUI thread instead
of constantly badgering it with bits of work to do.
Now take a read here:
You should not use ConfigureAwait when you have code after the await
in the method that needs the context. For GUI apps, this includes any
code that manipulates GUI elements, writes data-bound properties or
depends on a GUI-specific type such as Dispatcher/CoreDispatcher.
You're doing exactly the opposite. You're trying to update GUI in two points, one in your callback method, and another here:
var c = new ClassFromMyLibrary1();
var v1 = c.MethodFromMyLibrary1("test1", ActionToProcessNewValue).Result;
Label2.Content = v1; // updating GUI...
That's why removing ConfigureAwait(false) solves your problem. Also, you can make your button click handler async and await your ClassFromMyLibrary1 method call.
In my opinion, you should redesign your library API to not mix a callback-based API with a Task-based API. At least in your example code there's no compelling case to be made to do that and you've nailed one reason not do do that - it is hard to control the context in which your callback runs.
I'd change your library API to be like so:
namespace MyLibrary1
{
public class ClassFromMyLibrary1
{
public async Task<string> MethodFromMyLibrary1(string key)
{
var remoteValue = await GetValueByKey(key).ConfigureAwait(false);
return remoteValue;
}
public string TransformProcessedValue(string processedValue)
{
return string.Format("Processed-{0}", processedValue);
}
private async Task<string> GetValueByKey(string key)
{
//simulate time-consuming operation
await Task.Delay(500).ConfigureAwait(false);
return string.Format("ValueFromRemoteLocationBy{0}", key);
}
}
}
And call it like so:
private async void Button1_OnClick(object sender, RoutedEventArgs e)
{
try
{
var c = new ClassFromMyLibrary1();
var v1 = await c.MethodFromMyLibrary1("test1");
var v2 = await ActionToProcessNewValue(v1);
var v3 = c.TransformProcessedValue(v2);
Label2.Content = v3;
}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError("{0}", ex);
throw;
}
}
private Task<string> ActionToProcessNewValue(string s)
{
Label1.Content = s;
return Task.FromResult(string.Format("test2{0}", s));
}
So I'm trying to write a simple universal app to get the price of bitcoin from the web. I have an async method that I got from here to get the json from a url and put it into a string. Here is where I called the method:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
CoinPriceBackend CP = new CoinPriceBackend();
string response = await GetFromAPI();
}
And this is the method:
async Task<string> GetFromAPI()
{
try
{
//Create HttpClient
HttpClient httpClient = new HttpClient();
//Define Http Headers
httpClient.DefaultRequestHeaders.Accept.TryParseAdd("application/json");
//Call
string ResponseString = await httpClient.GetStringAsync(
new Uri("https://api.bitcoinaverage.com/ticker/GBP/"));
//Replace current URL with your URL
return ResponseString;
}
catch (Exception ex)
{
return "ERROR: " + ex;
}
}
I get the error
'The 'await' operator can only be used within an async method.
Consider marking this method with the 'async' modifier and changing its return type to 'Task'.'
But the method is async... How can I fix this?
Thanks!
But the method is async
Take a closer look at the error message; it's not talking about GetFromAPI - it's talking about App.
However, as others have pointed out, constructors cannot be marked async.
I'm trying to write a simple universal app
Universal Windows apps - like all other modern platforms - cannot block the UI thread for I/O-based operations. The user experience is just too bad, and there are tests in most app stores to auto-reject apps that do this.
Put another way: App is called (presumably) on application startup. When the user launches your app, it has to start up quickly and show something ASAP. Waiting for a download to complete is simply not an option.
So, to really fix this, you need to just start the download (not waiting for it to complete) and initialize your application to a "loading" state - showing a spinner or "Loading..." message or whatever. Then, when the download completes, update your app to display what you need to.
I have a blog post on async constructors and an article series on async MVVM (if you're doing MVVM), but a really basic approach could look something like this:
public Task Initialization { get; }
public string Value { get; private set { /* code to raise PropertyChanged */ } }
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
CoinPriceBackend CP = new CoinPriceBackend();
Value = "Loading..."; // Initialize to loading state.
Initialization = InitializeAsync();
}
private async Task InitializeAsync()
{
try
{
string response = await GetFromAPI();
...
Value = response; // Update data-bound value.
}
catch (Exception ex)
{
... // Display to user or something...
}
}
When you use an await within a function you should define the function as async.
But for App() constructor you will be unable to do that. You can defined another function from which you can call your function which return string.
Like this
public App()
{
CallApi();
}
private async void CallApi()
{
response = await GetFromAPI();
}
C# does not allow constructors to be marked as async.
You have three main options:
1) refactor to call this method in async event handler;
2) spawn a new thread using Task.Run and run async code there. This could lead to issues of marshalling result back to UI thread and assigning value to some UI element;
3) make it synchronous (blocking) call. This probably is the easiest option.
You will have to make following changes.
string response = GetFromAPI().Result;
Note that this will probably cause deadlock as Task will try to reaume in the main thread, which is already locked by call to '.Result', therefore you need another change. Also, there is no point
Task<string> GetFromAPI()
{
....
return httpClient.GetStringAsync(new Uri("https://api.bitcoinaverage.com/ticker/GBP/")).ConfigureAwait(false);
...
}
I am trying to call a REST service using RESTSharp and continuing execution immediately as I just need a task started but need to continue execution immediately so I am trying to use ExecuteAsync instead of Execute.
My code should look like this now
IRestResponse<ExpandoObject> restResponse = client.ExecuteAsync<ExpandoObject>(restRequest, response =>
{
callback(response.Content);
});
However, I have no idea how to implement the callback function and all samples don't show it. I assume it is like this but it does not compile.
private IRestResponse<ExpandoObject> callback(string content)
{
return null;
}
Any ideas?
There are a few ways to implement what you're trying to do, but the it looks like your
callback has wrong method signature...to get something "basic" running, the following should work
(I added wait simply for testing):
EventWaitHandle resetEvent = new AutoResetEvent(false);
client.ExecuteAsync(request, response =>
{
callback(response.Content);
resetEvent.Set();
return;
});
resetEvent.WaitOne();
}
private static void callback(string content)
{
System.Console.WriteLine(content);
}
I'm busy with a windows phone application that of course uses silverlight. This means that calling any webservices has to be done asynchronously, and since this is all good and well in regards to best practice in preventing your entire app in hanging when waiting for a resource, I'm still stuck in the "synchronous mindset"...
Because the way I see it now is that you end up having 2 methods that needs to handle one function, e.g:
1)The method that actually calls the webservice:
public void myAsyncWebService(DownloadStringCompletedEventHandler callback)
{
//Url to webservice
string servletUrl = "https://deangrobler.com/someService/etc/etc"
//Calls Servlet
WebClient client = new WebClient();
client.DownloadStringCompleted += callback;
client.DownloadStringAsync(new Uri(servletUrl, UriKind.Absolute));
}
2) and the method that handles the data when it eventually comes back:
private void serviceReturn(object sender, DownloadStringCompletedEventArgs e)
{
var jsonResponse = e.Result;
//and so on and so forth...
}
So instead of having to just create and call a single method that goes to the webservice, gets the returned result and sent it back to me like this:
public string mySyncWebService(){
//Calls the webservice
// ...waits for return
//And returns result
}
I have to in a Class call myAsyncWebService, AND create another method in the calling class that will handle the result returned by myAsyncWebService. Just, in my opinion, creates messy code. With synchronous calls you could just call one method and be done with it.
Am I just using Asynchronous calls wrong? Is my understanding wrong? I need some enlightment here, I hate doing this messy-async calls. It makes my code too complex and readability just goes to... hell.
Thanks for anyone willing to shift my mind!
You have to turn your mind inside out to program asynchronously. I speak from experience. :)
Am I just using Asynchronous calls wrong? Is my understanding wrong?
No. Asynchronous code is fairly difficult to write (don't forget error handling) and extremely difficult to maintain.
This is the reason that async and await were invented.
If you're able to upgrade to VS2012, then you can use Microsoft.Bcl.Async (currently in beta) to write your code like this:
string url1 = "https://deangrobler.com/someService/etc/etc";
string jsonResponse1 = await new WebClient().DownloadStringTaskAsync(url1);
string url2 = GetUriFromJson(jsonResponse1);
string jsonResponse2 = await new WebClient().DownloadStringTaskAsync(url2);
Easy to write. Easy to maintain.
Async is like when you make a telephone call and get an answering machine, if you want a return call you leave your number. The first method is your call asking for data, the second is the "number" you've left for the return call.
It all becomes much easier and readable if you use lambdas instead. This also enables you to access variables declared in the "parent" method, like in the following example:
private void CallWebService()
{
//Defined outside the callback
var someFlag = true;
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
//Using lambdas, we can access variables defined outside the callback
if (someFlag)
{
//Do stuff with the result.
}
};
client.DownloadStringAsync(new Uri("http://www.microsoft.com/"));
}
EDIT: Here is another example with two chained service calls. It still isn't very pretty, but imho it is a little more readable than the OPs original code.
private void CallTwoWebServices()
{
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
//1st call completed. Now make 2nd call.
var client2 = new WebClient();
client2.DownloadStringCompleted += (s2, e2) =>
{
//Both calls completed.
};
client2.DownloadStringAsync(new Uri("http://www.google.com/"));
};
client.DownloadStringAsync(new Uri("http://www.microsoft.com/"));
}
To avoid creating messy code, if you can't use the async / await pattern because you are on older framework, you will find helpful check CoRoutines in their Caliburn Micro implemantation. With this pattern you create an enumerable yielding at each turn a new asynchronous segment to execute: by the reader point of view asynchronous steps appear as a sequence, but walking among the steps ( so yielding the next one ) is done externally by asynchronously wait the single task. It is a nice pattern easy to implement and really clear to read.
BTW if you don't want to use Caliburn Micro as your MVVM tool because you are using something else, you can use just the coroutine facility, it is very insulated inside the framework.
Let me just post some code from an example in this blog post.
public IEnumerable<IResult> Login(string username, string password)
{
_credential.Username = username;
_credential.Password = password;
var result = new Result();
var request = new GetUserSettings(username);
yield return new ProcessQuery(request, result, "Logging In...");
if (result.HasErrors)
{
yield return new ShowMessageBox("The username or password provided is incorrect.", "Access Denied");
yield break;
}
var response = result.GetResponse(request);
if(response.Permissions == null || response.Permissions.Count < 1)
{
yield return new ShowMessageBox("You do not have permission to access the dashboard.", "Access Denied");
yield break;
}
_context.Permissions = response.Permissions;
yield return new OpenWith<IShell, IDashboard>();
}
Isn't it easy to read? But it is is actually asynchronous: each yield steps are executed in an asynchronous manner and the execution flow again after the yield statement as soon the previous task completed.
With synchronous calls you could just call one method and be done with it.
Sure, but if you do that from the UI thread you will block the entire UI. That is unacceptable in any modern application, in particular in Silverlight applications running in the browser or in the phone. A phone that is unresponsive for 30 seconds while a DNS lookup times out is not something anybody wants to use.
So on the UI thread, probably because the user did some action in the UI, you start an asynchronous call. When the call completes a method is called on a background thread to handle the result of the call. This method will most likely update the UI with the result of the asynchronous call.
With the introduction of async and await in .NET 4.5 some of this "split" code can be simplified. Luckily async and await is now available for Windows Phone 7.5 in a beta version using the NuGet package Microsoft.Bcl.Async.
Here is a small (and somewhat silly) example demonstrating how you can chain two web service calls using async. This works with .NET 4.5 but using the NuGet package linked above you should be able to do something similar on Windows Phone 7.5.
async Task<String> GetCurrencyCode() {
using (var webClient = new WebClient()) {
var xml = await webClient.DownloadStringTaskAsync("http://freegeoip.net/xml/");
var xElement = XElement.Parse(xml);
var countryName = (String) xElement.Element("CountryName");
return await GetCurrencyCodeForCountry(countryName);
}
}
async Task<String> GetCurrencyCodeForCountry(String countryName) {
using (var webClient = new WebClient()) {
var outerXml = await webClient.DownloadStringTaskAsync("http://www.webservicex.net/country.asmx/GetCurrencyByCountry?CountryName=" + countryName);
var outerXElement = XElement.Parse(outerXml);
var innerXml = (String) outerXElement;
var innerXElement = XElement.Parse(innerXml);
var currencyCode = (String) innerXElement.Element("Table").Element("CurrencyCode");
return currencyCode;
}
}
However, you still need to bridge between the UI thread and the async GetCurrencyCode. You can't await in an event handler but you can use Task.ContinueWith on the task returned by the async call:
void OnUserAction() {
GetCurrencyCode().ContinueWith(GetCurrencyCodeCallback);
}
void GetCurrencyCodeCallback(Task<String> task) {
if (!task.IsFaulted)
Console.WriteLine(task.Result);
else
Console.WriteLine(task.Exception);
}