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);
}
Related
Sometimes I need to start an async job which works very slow. I don't care if that job success and I need to continue working on my current thread.
Like sometimes I need to send an Email or SMS which works very slow. I need to respond to the web client as soon as possible so I don't want to await it.
I have googled this question and some articles suggest me to write like this:
// This method has to be async
public async Task<Response> SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Run(() => _emailService.SendEmailAsync());
return MyRespond();
}
Or like this:
// This method has to be async
public async Task<Response> SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Factory.StartNew(() => _emailService.SendEmailAsync());
return MyRespond();
}
There will be a warning says: before the call is completed. Consider applying the 'await' operator to the result of the call.
So what if I really awaited it? What is the best practice in C# to 'fire and forget', just call an async method without waiting for its completion?
A standalone discard is the best way to avoid this warning.
_ = Task.Run(() => _emailService.SendEmailAsync());
Discards are dummy variables and can be used to ignore the Task object returned by an asynchronous operation.
https://learn.microsoft.com/en-us/dotnet/csharp/discards#a-standalone-discard
If you truly just want to fire and forget. Simply don't call use await.
// It is a good idea to add CancellationTokens
var asyncProcedure = SomeHTTPAction(cancellationToken).ConfigureAwait(false);
// Or If not simply do:
var asyncProcedure = SomeHTTPAction().ConfigureAwait(false);
If you want to use the result output later its gets trickier. But if it is truly fire and forget the above should work
A Cancellation token allows interrupts and canceling procedures. If you are using Cancellation token you will need to use it everywhere from the retrieval straight through to the calling method (Turtles all the way down).
I used ConfigureAwait(false) to prevent deadlocks. Here for more information
EDIT
See the second answer that uses 'Task.Factory.StartNew' I gave this answer some time ago. At the time I didn't realise that the way I did it at the time doesn't ensure completion.
If you need to use async in your function you can also use a discard variable and don't use await. This is also usefull if you have multiple async function calls but you don't need to wait for all of them.
public async function(){
var tmp = await asyncfunction();
...
_ = _httpClient.PutAsync(url, content);
...
}
As Amadan told in the comment that, you need to remove async from your function. then it will stop giving you the warning.
// This method has to be async
public Response SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Factory.StartNew(() => _emailService.SendEmailAsync());
return MyRespond();
}
and Task.Factory.StartNew(() => _emailService.SendEmailAsync()); will indeed work on a new thread.
It all depends on what your Async method accepts. Normally it will accept a "special" class that also holds an event. You can subscribe your callback method to that event and pass it along with the method. When it's finished, your callback method will be called.
An example of this (for sockets) would be:
public void CreateSocket()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs sockAsync = new SocketAsyncEventArgs();
sockAsync.Completed += SockAsync_Completed;
s.ConnectAsync(sockAsync);
}
private void SockAsync_Completed(object sender, SocketAsyncEventArgs e)
{
//Do stuff with your callback object.
}
It all depends on what the method you are trying to call can accept. I would look at the documentation for more help on that specifically.
I am curious why this hasn't been suggested.
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
//what ever code here...e.g.
DoSomething();
UpdateSomething();
}).Start();
It just fires off a separate thread.
I'm calling a third-party API which has a method that looks like this:
myServiceClient.Discover(key, OnCompletionCallback);
public bool OnCompletionCallback(string response)
{
// my code
}
My challenge is, I have to call Discover because it does some work under-the-covers that I need. At the same time, I have to wait for Discover to complete before running my custom code. To further complicate matters, I can't just put my code in the OnCompletionCallback handler because I need to call the code above from a Func delegate. In short, I want to do this:
Func<SystemTask> myFunction = async () =>
{
await myServiceClient.Discover(key);
// my code
}
However, I can't do this because the third-party API uses a callback approach instead of an async/await approach.
Is there some way to make the callback approach work in an async / await world?
If I understand you correctly you can do something like this
public Task<bool> MyAsyncFunction()
{
var tcs = new TaskCompletionSource<bool>();
myServiceClient.Discover("somekey", s => {
//........
var res = true;
tcs.TrySetResult(res);
return res;
});
return tcs.Task;
}
Now you can await MyAsyncFunction
I am trying to invoke a method from another .dll file .
It is sending a message through the VPN then Return the RecievedMessage from another computer.
As you now it takes time to sending and receiving message and VpnObject just send message and I should wait for listener to invoke the RecievedMessage.
This method is like this!
public string RecievedMessage()
{
string Recieved ;
// Some VPN Code and then return the result;
return Recieved;
}
public string SendAndRecieveMessage(string MessageToSend)
{
string RecievedAnswer = string.Empty;
// Now Sending Message through the VPN
VpnObject.SendMessage(MessageToSend);
//Then want to Recieve the answer and return the answer here .
return RecievedAnswer;
}
I'm just thinking how can wait for RecievedMessage to invoke then return the result .
You know it is simple to use a variable and assign it value and check for while but it reduced the performance dramatically .
Is there anyway to continue from SendAndRecieveMessage just when RecievedMessage invoked ? (I think it is something with async and await but don't know how!)
Edit :VpnObject is just a sender and receiver through the vpn . it contains a simple socket send and a listener that invoke a method(RecievedMessage) when new message received .
Whether or not you have an alternative to polling depends on whether the library you are using provides any events or callbacks that will tell you when the request has completed.
Either way, the standard approach to exposing the deferred result of an asynchronous operation is to use a Task. Your method signature would look like this:
public Task<string> SendAndRecieveMessage(string MessageToSend)
Now, how you actually implement the method depends on what API VpnObject exposes. TaskCompletionSource is very useful for this kind of thing.
If VpnObject has an event that fires when the request completes:
public Task<string> SendAndReceiveMessage(string messageToSend)
{
var tcs = new TaskCompletionSource<string>();
...
VpnObject.OnMessageReceived += (s, e) => tcs.SetResult(e.Message);
...
return tcs.Task;
}
If VpnObject can accept a callback that it will invoke when the request completes:
public Task<string> SendAndReceiveMessage(string messageToSend)
{
var tcs = new TaskCompletionSource<string>();
...
VpnObject.OnMessageReceived(message => tcs.SetResult(message));
...
return tcs.Task;
}
If VpnObject doesn't support any of this, you can fall back to polling:
public async Task<string> SendAndReceiveMessage(string messageToSend)
{
var tcs = new TaskCompletionSource<string>();
...
while(!VpnObject.IsMessageReceived)
await Task.Delay(500); // Adjust to a reasonable polling interval
...
return VpnObject.Message;
}
You know it is simple to use a variable and assign it value and check for while but it reduced the performance dramatically .
A spin while loop is definitely not the way to implement this. Even with a sleep, it's clunky, and C# has multiple ways to solve this problem.
It's not entirely clear how your VPN Send and Receive method works, but the idea for solving this is to either use a callback approach, or as you noted, use C# async framework.
Without more details on the VPN Object, I'll just have to have some stub methods. The idea is to create a Task that returns the string, mark it as an async task, then await for it to complete. In your case, the task is receiving the VPN response string.
Something like this.
public Task<string> ReceivedMessage()
{
//get the response from the VPN Object.
string Received = VpnObject.GetResponse();
var ts = new TaskCompletionSource<string>();
ts.SetResult(Received);
// Some VPN Code and then return the result;
return ts.Task;
}
public async Task<string> SendAndReceiveMessageAsync(string MessageToSend)
{
string result = string.Empty;
// Now Sending Message through the VPN
VpnObject.SendMessage(MessageToSend);
result = await ReceivedMessage();
return result;
}
So I have a function that has a long wait time during its computation. I have a endpoint that needs to call this function, however it does not care about the completion of the function.
public HttpResponseMessage endPoint
{
Repository repo= new Repository();
// I want repo.computeLongFunction(); to be called, however this endpoint
// can return a http status code "ok" even if the long function hasn't completed.
repo.computeLongFunction();
return Request.CreateReponse(HttpStatusCode.Ok);
}
// If I make the function async would that work?
public class Repository
{
public void compluteLongFunction()
{
}
}
Use the Task Parallel Library (TPL) to spin off a new thread.
Task.Run(() => new Repository().computeLongFunction());
return Request.CreateReponse(HttpStatusCode.Ok);
It doesn't look like computeLongFunction() returns anything, so try this:
Thread longThread = new Thread(() => new Repository().computeLongFunction());
longThread.Start();
return Request.CreateResponse(HttpStatusCode.Ok);
Declare the thread so that you will still be able to control its life-cycle.
I'm at my wits end trying to solve this issue.
I have a function in a class as such
public class ReceiveData
{
Dataprovider provider = new DataProvider();
public void ResponseData()
{
foreach(string anItem in TheList)
{
// AllData function is declared in class DataProvider
string result = provider.AllData(anItem);
}
//do something
}
}
That's simple. However, what would I do if AllData function had to make async function calls to get data?
Meaning, say
public class DataProvider
{
MyServiceClient client = new MyServiceClient();
public string AllData (string myItem)
{
client.FormattedDataCompleted += new EventHandler<FormattedDataCompletedEventArgs>(client_FormattedDataCompleted);
client.FormattedDataAsync(myItem);
}
void client_FormattedDataCompleted(object sender, FormattedDataCompletedEventArgs e)
{
// here's where the response comes back.
}
As you can see, now I cant simply call AllData function and directly get data back.
So, what would I have to do in ResponseData function to make sure I call the AllItem function, and get data back from the callback. Notice that there's a loop in that function, so I need to all the parameters I have sent through the loop gets respective response.
One approach I tried was by using AutoResetEvent class.
I defined a handler for this as
AutoResetEvent handle = new AutoResetHandle(false);
then I add handle.WaitOne() right after the async call. and on the callback, added handle.Set();
However, the applications get stuck at handle.WaitOne(). So I can't really see why that happens.
I now have a theoritical idea to see if I could have a event raiser on the callback, and an eventlistener in RecieveData class, and if those two communicate, I could get the data. But I've spent some time trying to learn more about event handlers, but haven't gotten the hang of it.
So does anybody have any other approach, ideas? Thanks!
Welcome to the asynchronous model. You have to re-think how you call methods when you go multithreaded.
You have some options:
Split the method in which you're making the call into two halves; in the first half, call AllData, do ANYTHING else you can possibly do without having the response object, and then exit your current method. When the async call completes, it'll call your handler, where you should perform all operations from the original method that require the response.
In the event handler for the async call completion, set a property that indicates the call is completed, and put the data out on a property somewhere as well. In the function that kicks off the call, at the point where you simply cannot continue execution until the call completes, wait in a while loop for the call to complete by polling the property and breaking once it indicates the call has been completed (you'll probably want a Thread.Yield() in the loop as well that you'll call when you haven't gotten a response yet, to make sure you aren't blocking other threads doing more important things than waiting)
Wrap your asynchronous call in a class that exposes a synchronous method. The wrapper class will have similar logic as integrating the async call into your method. It will make the call, wait for the response, and return that response as if it were a normal synchronous method call.
Remember that the asynchronous call is giving your calling thread the opportunity to do other work while the call is performed. Take full advantage of this if at all possible.
You just need to use a delegate and call BeginInvoke. You can then set a callback method to capture the result of the delegate call.
public class ReceiveData
{
private List<string> TheList = new List<string>
{
"1", "2", "3"
};
dynamic provider = new ExpandoObject();
public void ResponseData()
{
foreach (string anItem in TheList)
{
// AllData function is declared in class DataProvider
Func<string, string> asyncAllData = provider.AllData;
asyncAllData.BeginInvoke(anItem, AllDataDone, null);
}
//do something
}
private void AllDataDone(IAsyncResult iar)
{
AsyncResult ar = (AsyncResult)iar;
var del = (Func<string, string>)ar.AsyncDelegate;
// here's your result
string result = del.EndInvoke(iar);
}
}