Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm trying to create an Web Service that runs an asynchronous function with .Net Core Framework.
This function must be executed in its own thread and return a new value that will be sent to the proper caller.
The service must be listening for other calls while my async function is running, and start a new thread for each call.
Once the thread is finished, I want the response to be sent to the original caller.
I have tried this way :
In my controller I have :
[Route("api/orchestration")]
public class OrchController : Controller
{
[HttpGet("{value}")]
public void RunOrchestration(int value)
{
Program.GetResultAsync(value); // Notice that no value is returned but it respects the asynchronicity and the multithreading as asked
}
}
In my main class I have :
public async static Task<string> GetResultAsync(int i)
{
return await OrchestrationAsync(i);
}
public static Task<string> OrchestrationAsync(int i)
{
return Task.Run<string>(() => { return r = Orchestration(i); });
}
public static string Orchestration(Object i)
{
// This function is an orchestrator of microservices that talk asynchronously through a MOM
// Just consider that it returns the value I want in a string
return result;
}
As you can see I want my function GetResultAsync to return a string with the value that will be sent to the caller.
Yet I can't have something like this (see code below) because GetResultAsync returns a Task and not a string :
public string RunOrchestration(int value)
{
return r = Program.GetResultAsync(value);
}
And if I put an await in RunOrchestration, it will wait for the response and will behave as a synchronous function.
Anyone has an idea on how to get my response and give it back to the proper caller ?
Thank's in advance ! :)
I wish I could just somehow broadcast at once to every .NET developer in the world: async is not multithreading/parallel processing/background processing, etc.
Async does one and only one thing: it allows the current thread to be returned to the pool if it's idle. That's it. Period. End of story. If you're doing something like creating a new thread, that effectively idles the original thread allowing it to be returned to the pool, but you still have a thread. In other words, you did absolutely nothing but add a bunch of overhead and context switching to your code, making it less efficient, not more.
What you need here is a true background process. You can use something like Hangfire to fire off a task, and then that task can be handled by something. That could be a console app, another web application, an Azure Function, whatever. The point is that it's external to your main web application. Then, you can immediately return, without waiting for that thing, whatever it is, to finish. You can, also, utilize something like SignalR and web workers to push status updates to the client.
Of course, the return value of GetResultAsync is Task (not a string) This is exactly what it should be. You probably misunderstood the concept of await/async. if you want string - you should call
await Program.GetResultAsync(value)
Read this topic :
How and When to use `async` and `await`
Nevertheless, such construction is futile. You are not gaining anything by async/await here.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
In a WPF desktop app, I need to integrate with a third party API that takes a synchronous callback function. In this callback, I need to display a message provided by the third party software, wait for user input and then return that input to the third party software.
The interaction with the user will be in my main window (not a modal dialog), so the UI thread must not be blocked while in the callback function.
There are a number of ways to do this: threads & AutoResetEvent, DispatcherTimer, etc. But most articles describing these methods were written before the async features of .Net 4.5 were available. Nowadays, is there any reason to do anything more complex than the following?
{
...
// Call 3rd party code passing our callback function
thirdParty.Process(referenceNumber, amount, GetValue))
...
}
// UI sets this variable from the user's input
private string _getValueResponse = null;
// The callback function passed to third party API
private void GetValue(ref ClientInstruction clientInstruction)
{
var message = clientInstruction.Message;
_getValueResponse = null;
// This event passes the 3rd party message to my main window,
// and causes it to prompt for user input.
GetValueRequired?.Invoke(this, new GetValueRequiredEventArgs(message));
var result = Task.Run<string>(
async () => await WaitForGetValueResponse())
.GetAwaiter().GetResult();
// Return user input to the third party code
clientInstruction.EnteredValue = result;
}
private async Task<string> WaitForGetValueResponse()
{
while (_getValueResponse == null)
{
await Task.Delay(100);
}
return _getValueResponse;
}
You can do it with BeginRead like pattern as below
Task.Run(() => thirdParty.Process(referenceNumber, amount, GetValue)))
.ContinueWith();
Task.Run will start new thread to get user input and return control back immediately.
And GetValue must be blocking call since third party software does not expect it async, is't it?
ContinueWith() must be populated with logic that processes user inputs and returns it back to your model
However I'm not sure that this is good. First problem is that Task.Run spawn new thread and UI dialog can fail to be shown properly. However you can handle it with dispatcher in WPF.
I suppose that waiting for user input should be blocking call and there is not too much benefit with non-blocking input.
You are using third party software and writing async GetValue will not work.
What would you like to achieve when saying "non-blocking user input in this case" ?
You are spinning up another thread just to await a result.
To be clear, there are three threads at play here.
Your UI thread
The thread that called your callback
A thread that you spin up with Task.Run()
This third thread is pointless, since all it does is sit and await a result from the UI thread, and the second thread sits and waits for the third thread!
If you are happy for the callback to block while you wait (which you current code does), why not just Sleep?
private void GetValue(ref ClientInstruction clientInstruction)
{
var message = clientInstruction.Message;
_getValueResponse = null;
// This event causes the UI to prompt for input
GetValueRequired?.Invoke(this, new GetValueRequiredEventArgs(message));
//poll for response
while (_getValueResponse == null)
Thread.Sleep(100);
clientInstruction.EnteredValue = _getValueResponse ;
}
However, this feels wrong to me. I doubt your third party API is expecting you to lock its callback thread, especially as it provides you with a context object to set the result?
Can you not just store the ClientInstruction in a member and set it directly from the UI thread?
I am trying to make a function that when called returns back information to the caller that is on a server. What I want in this function, is that it creates a thread that issues the command to the server, and then suspends itself until the server responds back with the answer.
public AccountState GetAccount(string key)
{
AccountState state = null;
Thread t = new Thread(() =>
{
_connection.SomeCommandSentToServer(key);
accountRequests.TryAdd(key, (Thread.CurrentThread, null));
//Suspend current thread until ServerReponseHere is called
Thread.CurrentThread.Suspend();
//We have been resumed, value should be in accountRequests now
accountRequests.TryRemove(key, out var item);
state = item.AccountState;
});
t.Start();
return state;
}
public ConcurrentDictionary<string, (Thread Thread, AccountState AccountState)> accountRequests = new ConcurrentDictionary<string, (Thread Thread, AccountState AccountState)>();
///Once server is done with processed command, call to this function made
public void ServerReponseHere(string key, AccountState state)
{
accountRequests.TryGetValue(username, out var item);
accountRequests.TryUpdate(username, (item.Thread, new AccountState()), item);
item.Thread.Resume();
}
My Idea then is that in a different function, when server responds back, it calls the ResumeThread function shown above.
C# says that Suspend / Resume are deprecated functions however, -- what is a better way to do this?
UPDATE
Clarification about "SomeCommandSentToServer" -- This just sends a command to the server via TCP sockets.
In that call, all that is really happening is a transmission to the server. I'm using a library that uses WinSock2.h call of "Send()" -- Yes I know it is a deprecated library... but the library I'm using requires it.
I have a separate thread that polls input from the server. So I have no way to "await" on this SomeCommandSentToServer -- I would need to await on some sort of call back function (aka the resume function I was mentioning) -- to make this work.
I am unsure how to do that
With all the information available from the question, here is what you should aim for when using the async / await pattern:
public async Task<AccountState> GetAccountAsync(string key)
{
// The method SomeCommandSentToServerAsync must be changed to support async.
AccountState state = await _connection.SomeCommandSentToServerAsync(key);
return state;
}
It is highly unlikely that you need anything else. By that, I mean you will not have to manipulate threads directly, put them in a concurrent dictionary and manually suspend or resume them because it looks horrible from a maintenance perspective ;)
.NET will take care of the threading part, meaning the magic of the async infrastructure will most likely release the current thread (assuming a call is actually made to the server) until the server returns a response.
Then the infrastructure will either use the existing synchronization context -if you are on a UI thread for instance- or grab a thread from the thread pool -if not- to run the rest of the method.
You could even reduce the size of the method a bit more by simply returning a Task with a result of type AccountState:
public Task<AccountState> GetAccountAsync(string key)
{
// The method SomeCommandSentToServerAsync must be changed to support async.
return _connection.SomeCommandSentToServerAsync(key);
}
In both example, you will haver to make the callers async as well:
public async Task TheCallerAsync()
{
// Grab the key from somewhere.
string key = ...;
var accountState = await <inst>.GetAccountAsync(key);
// Do something with the state.
...
}
Turning a legacy method into an async method
Now, regarding the legacy SomeCommandSentToServer method. There is a way to await that legacy method. Yes, you can turn that method into an asynchronous method that can be used with the async / await.
Of course, I do not have all the details of your implementation but I hope you will get the idea of what needs to be done. The magical class to do that is called TaskCompletionSource.
What it allows you to do is to give you access to a Task. You create the instance of that TaskCompletionSource class, you keep it somewhere, you send the command and immediately return the Task property of that new instance.
Once you get the result from your polling thread, you grab the instance of TaskCompletionSource, get the AccountState and call SetResult with the account state. This will mark the task as completed and do the resume part you were asking for :)
Here is the idea:
public Task<AccountState> SomeCommandSentToServerAsync(string key)
{
var taskCompletionSource = new TaskCompletionSource<AccountState>();
// Find a way to keep the task in some state somewhere
// so that you can get it the polling thread.
// Do the legacy WinSock Send() command.
return taskCompletionSource.Task;
}
// This would be, I guess, your polling thread.
// Again, I am sure it is not 100% accurate but
// it will hopefully give you an idea of where the key pieces must be.
private void PollingThread()
{
while(must_still_poll)
{
// Waits for some data to be available.
// Grabs the data.
if(this_is_THE_response)
{
// Get the response and built the account state somehow...
AccountState accountState = ...
// Key piece #1
// Grab the TaskCompletionSource instance somewhere.
// Key piece #2
// This is the magic line:
taskCompletionSource.SetResult(accountState);
// You can also do the following if something goes wrong:
// taskCompletionSource.SetException(new Exception());
}
}
}
Background Workflow:
I have a client (jquery/ajax html page) calling our RESTful WebAPI to get some data (Patient 'encounters' - e.g. admission to a hospital, visit to a clinic, etc.). e.g.
public async Task<string> GetEncounters(string patientId)
{
PatientChart patientChart = await _myService.GetPatientChart(patientId);
string message = string.Empty;
if (patientChart.Encounters.Status == PatientChart.StatusNotApplicable)
{
message = "List of Encounters is not available. A request has been made to retrieve it.";
_myService.GetEncounters(patientId); // async method without call to await
}
return message;
}
Question
What happens the "GetEncounters" call above where the await keyword is not applied?
From my understanding, async methods do NOT generate a new thread
so when the main thread dies, does that mean the call to GetEncounters will abort?
(Behind the scenes, the GetEncounters will fire off a long running process to get data and store it in, e.g. cache, for later retrieval).
If I step through the code, every executes as expected. Likewise, if I add in the await keyword, it also works. (But then I make the caller block)
What's the solution?
i.e. what is the best way to create a background task/thread to execute the code even though the main thread has died?
The solution depends on how reliable you want the work to be. I.e., if you return the "not available" message, how important is it to you that GetEncounters will run?
You should at the very least register the background work with ASP.NET (i.e., HostingEnvironment.QueueBackgroundWorkItem). A more reliable solution would save the background work in storage and have an independent backend for processing. I describe some modern approaches on my blog.
I have an ASP.NET MVC 3 site that connects to a WCF service. The WCF Service is independent from the site and is hosted in a Windows Service.
Most of the calls are synchronous, so it's not a problem to wait for the WCF to do it's thing.
However, one of those (already implemented) calls takes a bit too long, and, as it essentially does not output anything directly, I wanted to spin it on the service and forget about it.
So I changed my code from:
public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
WcfServiceProxy.DoSlowCalculation(calculationOptions);
ViewBag.Started = true;
return View();
}
to
public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
Task.Run(() =>
{
WcfServiceProxy.DoSlowCalculation(calculationOptions);
});
ViewBag.Started = true;
return View();
}
which, as I understand should start an asynchronous request, and return immediately. Still, the execution is completely synchronous, and the UI is frozen until the operation concludes.
What obvious thing am I missing?
Update:
Also, note that I would prefer not to change the server implementation to an async one, just to de-synchronize the call to the service on the call-site.
Moreover, I've noticed that the StartSlowCalculation method finishes executing, but the server does not return a response until the service method finishes executing.
The WCF Service Proxy just does:
public void DoSlowCalculation(CalculationOptions calculationOptions)
{
//some logging code
Channel.DoSlowCalculation(calculationOptions);
}
so it's completely synchronous, however that shouldn't matter as it should be executed on an independent thread.
A task operation can run in the calling thread, it depends on taskScheduler decision. To help TaskScheduler make a right decision regarding long running call you can specify task creation option TaskCreationOptions.LongRunning.
And you can check whether task operation is running in a separate thread:
int launchedByThreadId = Thread.CurrentThread.ManagedThreadId;
int launchedInThreadId = -1;
Task.Run(() =>
{
launchedInThreadId = Thread.CurrentThread.ManagedThreadId;
WcfServiceProxy.DoSlowCalculation(calculationOptions);
});
// then compare whether thread ids are different
BTW, are you using any kind of Task.Wait() operation? It will block calling thread as well.
EDIT:
You might find following post interesting Is Task.Factory.StartNew() guaranteed to use another thread than the calling thread?
So try out using Task.Factory.StartNew() and specify cancellation token even you do not need it, sounds weird but it seems this guarantees that task will not be run eventually in the calling thread. Correct me If I wrong.
I've done this before.
The most robust way would be to use Asynchronous Controller's, or better yet an independant service such as a WCF service.
But in my experience, i've just needed to do "simple", one-liner task, such as auditing or reporting.
In that example, the easy way - fire off a Task:
public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
//Some Synchronous code.
Task.Factory.StartNew(() =>
{
WcfServiceProxy.DoSlowCalculation(calculationOptions);
});
ViewBag.Started = true;
return View();
}
That's a simple example. You can fire off as many tasks as you want, synchronize them, get notified when they finish, etc.
For more details you can see this links.
https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx
I want to use recent C# 5.0 async methods, however some specific way.
Consider following example code:
public abstract class SomeBaseProvider : ISomeProvider
{
public abstract Task<string> Process(SomeParameters parameters);
}
public class SomeConcreteProvider1 : SomeBaseProvider
{
// in this method I want to minimize any overhead to create / run Task
// NOTE: I remove here async from method signature, because basically I want to run
// method to run in sync!
public override Task<string> Process(SomeParameters parameters) {
string result = "string which I don't need any async code to get";
return Task.Run(() => result);
}
}
public class SomeConcreteProvider2 : SomeBaseProvider
{
// in this method, it's OK for me to use async / await
public async override Task<string> Process(SomeParameters parameters) {
var data = await new WebClient().DownloadDataTaskAsync(urlToRequest);
string result = // ... here we convert data byte[] to string some way
return result;
}
}
Now how I am going to use async methods (you can ignore fact that consumer actually ASP.NET MVC4 app in my case... it can be anything):
public class SomeAsyncController : AsyncController
{
public async Task<ActionResult> SomethingAsync(string providerId)
{
// we just get here one of providers I define above
var provider = SomeService.GetProvider(providerId);
// we try to execute here Process method in async.
// However we might want to actually do it in sync instead, if
// provider is actually SomeConcreteProvider1 object.
string result = await provider.Process(new SomeParameters(...));
return Content(result);
}
}
As you can see I have 2 implementations, each one will perform differently: one I want to run in async and do not block thread (SomeConcreteProvider2), while another one I want to be able to run in sync and do not create any Task object etc (which I fail to code in code above, i.e. I do create new Task here!).
There are questions already like How would I run an async Task<T> method synchronously?. However I don't want to run something in sync... I want to avoid any overhead if I know at code time (i.e. before runtime) that some methods implementations will NOT actually be async and will not need to use any threads / I/O completion ports etc. If you check code above, its easy to see that method in SomeConcreteProvider1 basically will construct some string (html), can do it very quickly at the same execution thread. However same method in SomeConcreteProvider2 will need to create Web Request, get Web Response and process it someway and I do want to make at least Web Request in Async to avoid blocking of whole thread during request time (may be quit long time actually).
So the question is: how to organize my code (different method signatures or different implementations, or?) to be able to decide how to execute method and avoid ANY possible overhead which caused for example by Task.Run(...) in SomeConcreteProvider1.Process method?
Update 1: obvious solutions (I think up some of them during question process), such as for example to add some static property to each of providers (say 'isAsyncImplementation') and then check that property to decide how to run method (with await or without await in controller action) have some overhead too :D I want something better if possible :D
In your first case, I would recommend returning:
Task.FromResult(result)
which returns a ready-completed task.
http://msdn.microsoft.com/en-us/library/hh194922%28v=vs.110%29.aspx
Your design looks fine.
For the SomeConcreteProvider1 case, you can use a TaskCompletionSource
This returns a Task without requiring concurrency.
Also, in the consumer code, await will not yield if the Task has already completed. This is called the "fast path" and effectively makes the method synchronous.