Error with HttpClient - c#

I have been working on a simple c# application that uses rest and Azure SQL Database. My app has two buttons one for saving new names and the second for showing them. the later doesn't react when i press it and i get the following error related to these parts GetRequest(); PostRequest(jsonPost);
private void Btn_Click(object sender, EventArgs e)
{
GetRequest();
}
private void Btn_Click(object sender, EventArgs e)
{
User user = new User(0, firstnameText.Text);
JavaScriptSerializer java = new JavaScriptSerializer();
String jsonPost = java.Serialize(user);
PostRequest(jsonPost);
}
}
Severity Code Description Project File Line Suppression State Detail Description
Warning CS4014 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. PersonRegister C:\Users\User\Downloads\RestSolution\RestSolution\PersonRegister\Form1.cs 86 Active The current method calls an async method that returns a Task or a Task and doesn't apply the await operator to the result. The call to the async method starts an asynchronous task. However, because no await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't what you expect. Usually other aspects of the calling method depend on the results of the call or, minimally, the called method is expected to complete before you return from the method that contains the call.
An equally important issue is what happens to exceptions that are raised in the called async method. An exception that's raised in a method that returns a Task or Task is stored in the returned task. If you don't await the task or explicitly check for exceptions, the exception is lost. If you await the task, its exception is rethrown.
As a best practice, you should always await the call.
You should consider suppressing the warning only if you're sure that you don't want to wait for the asynchronous call to complete and that the called method won't raise any exceptions. In that case, you can suppress the warning by assigning the task result of the call to a variable.

Although the advice to always return Task from an async method, this is not possible for UI event handlers. As such you should rewrite your handler like this:
private async void Button1_Click(object sender, EventArgs e)
{
await GetRequest();
}
private async void Button2_Click(object sender, EventArgs e)
{
Person p = new Person(0, nameText.Text);
JavaScriptSerializer js = new JavaScriptSerializer();
String jsonPost = js.Serialize(p);
await PostRequest(jsonPost);
}
See here for more info.
Also, as an aside, you should declare one static instance of HttpClient for the entire application (as per MSDN docs).

Related

How do I run an Async Task through IsActiveChanged

I have a Task which I'm trying to run through OnIsActiveChanged So that it runs when I open as a view. I'm sure I'm doing something obvious but I'm relatively new to Async code.
I'm getting an error with OnIsActiveChanged telling me
Task SettingsView.OnIsActiveChanged(object?, EventArgs) has the wrong return type.
Here is the method I'm trying to use:
public async Task OnIsActiveChanged(object? sender, EventArgs e)
{
if (IsActive)
{
var streaming = _client.BiStreaming();
var requestStream = streaming.RequestStream;
var responseStream = streaming.ResponseStream;
//Print
Debug.WriteLine($"Duration: {Duration.TotalSeconds} seconds");
Debug.WriteLine("");
await BidirectionalStreamingExample(_client);
}
}
And here is where I am trying to call the method:
public SettingsView(SequenceEditorService.SequenceEditorServiceClient client)
{
InitializeComponent();
_client = client;
IsActiveChanged += OnIsActiveChanged;
}
IsActiveChanged is an event handler that checks if there is a change in the state if the view. It was fine with the normal method i had but once i tried to async it broke.
There are two possible solutions to your question, as we would need to know what kind of return type the IsActiveChanged-event has. Typically events should have no return type (void) according to BCL guidelines, the possibility still exists though.
Possible solutions:
You have to return a Task (very unlikely as stated above)
Set the OnIsActiveChanged's return type to void (likely the solution, since IsActiveChanged is probably a event coded by Microsoft and therefore complies with the BCL guidelines)
When applying the second solution to your code, the OnIsActiveChanged's signature should look something like this:
public async void OnIsActiveChanged(object sender, EventArgs e)

Ordered execution of methods given they haven't been fired in order

I have two asynchronous methods (let's call them AAsync() and BAsync()) that are intended to run one after the other one. This is because method AAsync() prepares the context for method BAsync() to act properly. For each call of AAsync() there's a correspondent call of the method BAsync().
These methods can be fired in the following order (as an example):
A1A2B1B2A3B3B4A4, where A stands for AAsync, B for BAsync, and the subindex indicates the call number of the method.
Given that it will always be that method AAsynci will be called after method AAsynci-1 and before AAsynci+1 (same applies for BAsync), and that a call AAsynci has a correspondant call BAsynci, I would like to know which is the best way to, given a disordered firing of the methods (like the one in the example above), execute the calls in the following order:
A1B1A2B2A3B3A4B4 ...
I have solved this using two FIFO Semaphores and two TaskCompletionSource (see below), but I have the feeling that this can be solved in a smarter way. Does anybody know a nicer solution?
TaskCompletionSource TCS_A;
TaskCompletionSource TCS_B;
FIFOSemaphore MutexA = new FIFOSemaphore(1);
FIFOSemaphore MutexB = new FIFOSemaphore(1);
async void AAsync()
{
await MutexA.WaitAsync();
if (TCS_B!= null)
await TCS_B.Task;
TCS_B = new TaskCompletionSource<bool>();
// Do intended stuff...
TCS_A?.TrySetResult(true);
MutexA.Release();
}
async void BAsync()
{
await MutexB.WaitAsync();
if (TCS_A!= null)
await TCS_A.Task;
TCS_A = new TaskCompletionSource<bool>();
// Do intended stuff...
TCS_B?.TrySetResult(true);
MutexB.Release();
}
My suggestion is to use two Channel<T> instances. The channel A should receive the arguments passed to the A event handler, and the channel B should receive the arguments passed to the B event handler. Finally perform an asynchronous loop that takes one item from the channel A and one from the channel B ad infinitum:
Channel<EventArgs> _channelA = Channel.CreateUnbounded<EventArgs>();
Channel<EventArgs> _channelB = Channel.CreateUnbounded<EventArgs>();
void EventA_Handler(EventArgs e)
{
_channelA.Writer.TryWrite(e);
}
void EventB_Handler(EventArgs e)
{
_channelB.Writer.TryWrite(e);
}
async void EventHandlerLoop()
{
while (true)
{
EventArgs a = await _channelA.Reader.ReadAsync();
// Do intended stuff...
EventArgs b = await _channelB.Reader.ReadAsync();
// Do intended stuff...
}
}
The method EventHandlerLoop should be invoked during the initialization of the class, to start the wheel rolling.
If you are not familiar with the channels, you could take a look at this tutorial.

C# - return boolean from Async method

I have Async method which is called inside button_click. Async method runs 3 different void's and each void has It's own error handling. If any error inside those 3 methods occure I want to show that particular error message and stop code inside button_click - which also runs more non-async method and has It's error handling. What I did was this (example):
private void button1_Click(object sender, EventArgs e)
{
try
{
//calling non-async method, if It fails It should show error
//inside this event
Method1();
if (TestAsync().IsCanceled)
{
return;
}
MessageBox.Show("Test");
}
catch (Exception)
{
MessageBox.Show("Async method failed and this message should not be diplayed!");
throw;
}
}
public async Task<bool> TestAsync()
{
bool completed = await Task.Run(() => MethodToComplete());
return completed;
}
private bool MethodToComplete()
{
try
{
//renaming file, but intentionally fail for test purpose
Directory.Move("fail_this_method", "fail");
return true;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
return true;
throw;
}
}
The result of this example is - It does display error message from void which is called asynchronously and doesn't show error message from button_click. But It also displays MessageBox.Show("Test"); which shouldn't, code in button_click should stop immidiately if Async fails.
I hope I was clear enough, any help kindly appreaciated !
Before async-await there were other task handling methods, like Task.ContinueWith, Task.IsCanceled etc.
If you plan to use async-await, don't mix them with these older functions.
When you decide to use async-await, stick to the following rules:
only declare a function async if it awaits a call to another async function
every async function should return Task<TResult> instead of TResult and Task instead of void
There is one exception: an async event handler returns void
Furthermore:
If you call an async function, but you do not need the result immediately, consider not to await yet, but do the other things. Start awaiting when you need the results of the async function
After the await the thread that continues may be a different thread. But it has the same context. This has the effect that you can regard this as if it is the original thread. No need for InvokeRequired, locks and mutexes
If you don't need the same context, consider ConfigureAwait(false) after the await. This will speed up the process, with the disadvantage that the continuing thread does not have the user interface context. Therefore you can't access windows Form controls.
Keeping this in mind, you code could be as follows:
private async void button1_Click(object sender, EventArgs e)
{
// this function must be async because if awaits
// it is an event hander, hence it returns void instead of Task
try
{
Method1();
// call TestAsync, if you do not need the result right now,
// do not await yet
var myTask = TestAsync();
// as soon as TestAsync has to await, it continues here:
// results from TestAsync are not available yet
DoSomeOtherProcessing();
// now you need the result from testAsync; await the Task
bool result = await myTask;
ProcessResult(result);
}
catch (Exception)
{
...
}
}
A Task that is cancelled, should throw TaskCanceledException. You should not check MyTask.IsCanceled, but catch this exception.
Articles that helped me understanding async-await
This interview with Eric Lippert Search somewhere in the middle for async-await. Eric compares async-await with a cook making dinner. Once he put on the kettle, he does not idly wait for the water to boil, but looks around to see if he can do other things instead, like chopping onions
async-await by the ever so helpful Stephen Cleary

What's the difference between awaiting async Task function and calling await inside a void function?

To understand the question please take a look on the await calls and the definition of the function InitSyncContext() of the following example.
Based on that i would like to know how the program will behave on each scenario because i don't fully understand what´s the difference between calling await InitSyncContext(store) and having a await call inside without returning a Task.
For reference i did a research before and i found a similar example here however i think it's different in my case.
*The following code is a simplified example from a real world code just for demonstration purposes.
void Main()
{
Initializer();
}
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
InitFileSync(store);
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
//------------- Second Method -------------
void Main()
{
Initializer();
}
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
InitFileSync(store);
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
What's the difference between awaiting async Task function and calling await inside a void function?
This is perhaps a very big question is best served by reading the fine article Async/Await - Best Practices in Asynchronous Programming by Mr Stephen Cleary.
Some summary points:
Avoid async void - Prefer async Task methods over async void methods
See also
Cleary, S, "Async/Await - Best Practices in Asynchronous Programming", March 2013, Microsoft, https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396, retrieved 14/7/2016
What's the difference between awaiting async Task function and calling await inside a void function?
The whole world! Everything...and then some. Let's take a step back and start with some of the basics.
You should go "async all the way", i.e.; if you're returning an awaitable (Task or Task<T>) these should correctly use the async and await keywords.
There are several things that need to be clarified here. You should not have async void methods, instead you should have async Task - the exception being event handlers (where the delegates are predefined as non-task returning) and the like. Let's examine and pick apart method one (I'm going to ignore the Main entry points):
One
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
...
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
You have an Initializer method that is immediately a code smell as it is async void. This should be async Task and it should have the "Async" suffix. Additionally, you have an InitSyncContext that takes on a store variable and invokes some client initialization work. The code smell here is that you are using async and await. This is not need on simple (single task) workloads like this. Instead you should simply use the return keyword. Example at the very bottom. Let's look at method two:
Two
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
...
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
Things have officially gone from bad to worse! With the misconceptions of the asynchronous nomenclatures, we have assumed that since one method appeared to work "ok" without taking into account the best practices that another method could follow suit. You made the InitSyncContext method async void. The reason methods should not be async void is that they are fire-and-forget. The internal async state machine doesn't have a Task to latch onto and therefore the state is lost. When you remove the caller's await you are saying start this asynchronous operation but you do not care about it's results.
Here is the correct way to implement the desired functionality:
Correct
private async Task InitializerAsync()
{
var store = InitLocalStore();
await InitSyncContextAsync(store);
...
}
// Simply return the task that represents the async operation and let the caller await it
private Task InitSyncContextAsync(MobileServiceSQLiteStore store)
{
return Client.SyncContext.InitializeAsync(store);
}
A note about the Main method from your snippets, if this is part of a console application - the top-level entry point into your async stack would invoke either .Result or .Wait().
Further reading
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396
In first example compiler generate something like this:
TheadPool.RunTask(()=>InitSyncContext(store)).ContinueWith(()=>InitFileSync(store))
At second — nothing interesting. Because nobody wait the end of the task. All calls will be in main thread exept await Client.SyncContext.InitializeAsync(store);

SOAP Client doesn't finish its job or maybe doesn't return anything?

I'm using SOAP Client in Windows RT, I'm using Windows 8.1 OS and VS 2013. Anyway, what I want to do is just a simple task which returns a some string values.
When I try to do await - async task it doesn't return anything or maybe it just simply loses itself trying to find the client. I couldn't find a problem.
I added service reference , when I look at it in Object Browser there doesn't seem a problem. I'm stuck any idea why it's happening?
Here's my code:
using Namespace.InfoGetter;
private void btn_Click(object sender, RoutedEventArgs e)
{
Info info = GetInfo("en-US");
txtInfo.Text = info.Result.Value;
}
async Task<Info> GetInfo(string culture)
{
InfoSoapClient client = new InfoSoapClient();
Task<InfoResponse> info = client.GetInfoAsync(culture); <<<<<<<<<<<
Info result = await info;
return result;
}
When debug comes to the line (which I put <<<) client.GetInfoAsync(culture) doesn't return anything and the method ends there too. What to do?
As your code example isn't accurate, i assume what is happening is that you have a deadlock, since you block on info.Result while your await in GetInfo is trying to marshal work back to your UI thread.
We're going to add the async keyword to your buttons click event handler and await on GetInfoAsync
Try this:
private async void btn_Click(object sender, RoutedEventArgs e)
{
Info info = await GetInfoAsync("en-US");
textInfo.Text = info.Value
}
private Task<Info> GetInfoAsync(string culture)
{
InfoSoapClient client = new InfoSoapClient();
return client.GetInfoAsync(culture);
}
Note i added the Async suffix to your GetInfo method to follow the TAP convention and removed the async keyword from GetInfoAsync as you don't really need to generate the extra state machine as all you do is return is return the result and not do additional work with it.

Categories