Async task will not produce the good response - c#

I'm trying to wait the end of function to perform some task. HEre is my architecture
A class for the windows service
A class for communication with a device, instanciated as "ilon". This class have access to another class, who permit me to use a webservice
From the windows service, i'm doing it :
Item_DataColl resultSet = ilon.read("Net/LON/10/LampDali1/nviRunHours");
Here is the definition of the read function of the "ilon" class:
internal Item_DataColl read(string UCPTName)
{
return ilonBind.invoke_command_READ("Net/LON/10/LampDali1/nviRunHours").Result;
}
Ilonbind variable is associated to a class who permit me to create a connection with the webservice. So he got a function named "invoke_command_read", defined as :
public async Task<Item_DataColl> invoke_command_READ(string UCPTName)
{
return await Task.Run(() => thread_command_READ_result(UCPTName));
}
On the same class, i finally have this function :
private Item_DataColl thread_command_READ_result(string UCPTName)
{
Item_DataColl resultSet = null;
if (UCPTName != null)
{
try
{
OnProgressBarUpdate(progressBar.UnknownEnd);
resultSet = connector.command_READ(UCPTName);
readOperationDone(resultSet);
OnConsoleWriting(string.Format("[READING] Lecture réussie : {0} = {1}", ((Dp_Data)resultSet.Item[0]).UCPTname, ((Dp_Data)resultSet.Item[0]).UCPTvalue[0].Value), ILonConnectorConsoleResultType.RESULT);
}
catch (Exception e)
{
OnConsoleWriting(e.ToString(), ILonConnectorConsoleResultType.ERROR);
}
finally
{
OnProgressBarUpdate(progressBar.Invisible);
}
}
return resultSet;
}
Instruction "resultSet = connector.command_READ(UCPTName)" work well, and no result will be return until the result of the webservice request. But i am not able to get any result of the webservice.
Are my Task used well ?

Are my Task used well?
No.
Here's what's going on:
The actual operation is a network call, so it's a perfect fit for async.
But the proxy gives you synchronous APIs, so you're blocking a thread. (not good)
So invoke_command_READ wraps the synchronous API in a Task.Run, so it blocks a thread pool thread. (not good)
Then read blocks on the task using Result, blocking two threads per request and causing a deadlock. (really bad)
Your code is sync-over-async-over-sync, which is notable for employing two anti-patterns (sync-over-async and async-over-sync) simultaneously.
To fix this, either go async all the way, or sync all the way. Async all the way is more efficient but requires async APIs on your proxy:
public async Task<Item_DataColl> invoke_command_READ(string UCPTName)
{
Item_DataColl resultSet = null;
if (UCPTName != null)
{
try
{
OnProgressBarUpdate(progressBar.UnknownEnd);
resultSet = await connector.command_READAsync(UCPTName);
readOperationDone(resultSet);
OnConsoleWriting(string.Format("[READING] Lecture réussie : {0} = {1}", ((Dp_Data)resultSet.Item[0]).UCPTname, ((Dp_Data)resultSet.Item[0]).UCPTvalue[0].Value), ILonConnectorConsoleResultType.RESULT);
}
catch (Exception e)
{
OnConsoleWriting(e.ToString(), ILonConnectorConsoleResultType.ERROR);
}
finally
{
OnProgressBarUpdate(progressBar.Invisible);
}
}
return resultSet;
}
internal Task<Item_DataColl> readAsync(string UCPTName)
{
return ilonBind.invoke_command_READ("Net/LON/10/LampDali1/nviRunHours");
}
Sync all the way would probably be easier, since your proxy is sync and your consuming code is sync:
internal Item_DataColl read(string UCPTName)
{
return ilonBind.invoke_command_READ("Net/LON/10/LampDali1/nviRunHours");
}
public Item_DataColl invoke_command_READ(string UCPTName)
{
return thread_command_READ_result(UCPTName);
}

Related

Applying 'extract a method' refactoring to an async method

'Extract a method' is one of the most important and frequently performed refactoring to keep code clean and readable. In many cases, we can apply it automatically and safely with all modern IDEs.
My question is what is the best approach to apply this to async methods in C# (and other languages with async keyward such as JavaScript, TypeScript etc.)
As an example, suppose we have a lengthy async method which can be logically grouped and decomposed into separate methods like below:
private async Task StartWriting()
{
if (IsCreatingNewDir)
{
SaveFile();
var writingSpec = _writingSpec.Model!;
if (!OkToStartWriting(writingSpec)) return;
await _jobQueue.EnterJob(writingSpec);
}
else
{
if (!OkToStartWritingFromExistingDir()) return;
try
{
await _jobQueue.EnterJobFromExistingJobDir(Path.GetDirectoryName(Path.GetDirectoryName(FilePath))!);
}
catch (InvalidOperationException ex)
{
DialogManager.ShowError(Localize("NoConversionResultInJobDir"));
Logger.LogError(ex, "Invalid job directory.");
}
}
}
If I just apply it with Visual studio (with resharper), each of the extracted fragments becomes also an async method.
public async Task StartWriting()
{
if (IsCreatingNewDir)
{
await StartWritingFromScratch();
}
else
{
await StartWritingFromExistingDir();
}
}
private async Task StartWritingFromScratch()
{
SaveFile();
var writingSpec = _writingSpec.Model!;
if (!OkToStartWriting(writingSpec)) return;
await _jobQueue.EnterJob(writingSpec);
}
private async Task StartWritingFromExistingDir()
{
if (!OkToStartWritingFromExistingDir()) return;
try
{
await _jobQueue.EnterJobFromExistingJobDir(Path.GetDirectoryName(Path.GetDirectoryName(FilePath))!);
}
catch (InvalidOperationException ex)
{
DialogManager.ShowError(Localize("NoConversionResultInJobDir"));
Logger.LogError(ex, "Invalid job directory.");
}
This is OK, as the logic is the same and async method can call another async method. However, considering that async method is really a syntactic sugar and it is converted to rather complex code under the hood, I wonder if it's additional overhead is legitimate just to keep code readable. I think that the original refactoring to normal methods, hidden assumption is that method call overhead is rather small and negligible.
Another option I can think of is to extract each fragment as a synchronous method returning a Task like this:
// Extract fragment as a regular synchronous method returning Task which is awaitable.
private Task StartWritingFromExistingDir()
{
if (!OkToStartWritingFromExistingDir()) return Task.CompletedTask;
try
{
return _jobQueue.EnterJobFromExistingJobDir(Path.GetDirectoryName(Path.GetDirectoryName(FilePath))!);
}
catch (InvalidOperationException ex)
{
DialogManager.ShowError(Localize("NoConversionResultInJobDir"));
Logger.LogError(ex, "Invalid job directory.");
return Task.CompletedTask;
}
}
The code looks a bit noisier as I have to return Task explicitly, but I think it performs better and in most cases easier to debug and test.
Is there a generally agreed known best practice for doing this refactoring to async methods?
If you are concerned about the additional overhead, modify the parent method like this:
public Task StartWriting()
{
if (IsReadOnly)
{
return StartWritingFromExistingDir();
}
else
{
return StartWritingFromScratch();
}
}
Now you are not creating any of the additional async overhead.

Should Semaphoreslim be in the controller instead of further down in the chain?

We have a deadlock like behaviour in our production-environment and I wonder if we use SemaphoreSlim correctly.
In our restapi the code looks like this:
public async Task<IActionResult> CreateAsync([FromBody] SomeModel someModel)
{
var result = await _someClass.CreateArende(someModel);
return result;
}
public async Task<IActionResult> RegisterAsync([FromBody] SomeModel someModel)
{
var result = await _someClass.RegisterArende(someModel);
return result;
}
No SemphoreSlim in controller level of our API but in someClass looks like this:
public class SomeClass
{
protected static SemaphoreSlim _semphoreSlimCreateArende = new SemaphoreSlim(1, 1);
public async virtual Task<SomeResponseDto> CreateArende(SomeModel someModel)
{
try
{
await _semphoreSlimCreateArende.WaitAsync();
}
finally
{
try
{
_semphoreSlimCreateArende.Release();
}
catch (Exception)
{
}
}
return new SomeResponseDto()
{
...
};
}
public async virtual Task<SomeResponseDto> RegisterArende(SomeModel someModel)
{
try
{
await _semphoreSlimCreateArende.WaitAsync();
}
finally
{
try
{
_semphoreSlimCreateArende.Release();
}
catch (Exception)
{
}
}
return new SomeResponseDto()
{
...
};
}
}
Should the SemaphoreSlim be in the controller level instead? Or should I change the controllers actions to not be async?
This question is a little disjointed, however lets try to make sense of it a little
Firstly lets get the pattern right
try
{
await _semphoreSlimCreateArende.WaitAsync();
// do your sync work here
}
finally
{
// if this throws you are certainly doing something wrong
_semphoreSlimCreateArende.Release();
}
Secondly, you should have your keyboard taken away from you for this
catch (Exception)
{
}
Don't ever blindly eat exceptions, and if you are getting them on _semphoreSlimCreateArende.Release you have serious problems already and you have to work out why
Should the semaphoreslim be in the controller level instead?
Use them at the level that makes the most sense, i mean if you need to sync a piece of code sync it there, not 13 levels up.
Or should i change the controllers actions to not be async?
if you have asnyc work make your controller async and let it propagate down the stack to your async code
We have a deadlock like behaviour in our production-environment and i
wonder if we use semaphoreslim correctly.
Woah, are we talking DataBase Deadlocks, or Context DeadLocks. Either way this all sounds a little fishy

Persist thread's context across async calls

I am trying to disentangle my logs by grouping my log messages together. Ideally, I'd append to each message some identifier indicating that it is part of a group of commands achieving some piece of work.
If this were a single threaded application, the thread's ID would be a candidate. However, this solution makes heavy use of async Tasks, which precludes its use. Is it possible to get something like the following to work, where every execution of Main() would always print out the same thread ID?
static async void Main()
{
var t = Task.Run(async () => await MyAsyncMethod());
await t;
}
private static async Task MyAsyncMethod()
{
Debug.WriteLine("Log message: {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Debug.WriteLine("Log message: {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Debug.WriteLine("Log message: {0}", Thread.CurrentThread.ManagedThreadId);
}
The best approach IMO is what #SriramSakthivel suggested: just generate an id and pass it around. If you have a "message" type, you could just add it to that type.
However, if this would cause too much of a code change, then you can pass it implicitly. I have a blog post with the gory details; the general idea is that you store the data as part of the logical call context:
public static class MyContext
{
private static readonly string name = Guid.NewGuid().ToString("N");
private sealed class Wrapper : MarshalByRefObject
{
public Guid Value { get; set; }
}
public static Guid CurrentContext
{
get
{
var ret = CallContext.LogicalGetData(name) as Wrapper;
return ret == null ? Guid.Empty : ret.Value;
}
set
{
CallContext.LogicalSetData(name, new Wrapper { Value = value });
}
}
}
Then you can use it from your code as such:
private static async Task MyAsyncMethod()
{
MyContext.CurrentContext = Guid.NewGuid();
Debug.WriteLine("Log message: {0}", MyContext.CurrentContext);
await Task.Delay(1000);
Debug.WriteLine("Log message: {0}", MyContext.CurrentContext);
await Task.Delay(1000);
Debug.WriteLine("Log message: {0}", MyContext.CurrentContext);
}
Note that this approach makes two crucial assumptions:
Your code runs on .NET 4.5 or newer.
The data being stored is immutable (which is true in this case, since Guid is immutable).
It looks like something like this will be builtin in .NET 4.6.

How to return data using await function in C# windows phone 8?

I'm new to C#. I
I've a problem related to async methods and await function in C# windows phone 8.0.
I've this http request and can get response. This is working fine and There is no issue...
public async static Task<List<MyAccountData>> GetBalance()
{
HttpClient = new HttpClient();
string response = await client.GetStringAsync("http://xxxx/xxx/xxx");
List<MyAccountData> data = JsonConvert.DeserializeObject<List<MyAccountData>>(response);
return data;
}
I've another class call MainModel
public class MainModel
{
public void LoadData()
{
}
}
So My problem is, I want to call that GetBalance method with in MainModel class and parse data to LoadData method(simply want 2 access Data with in LoadData method). LoadData method can't change return type or can't use async. So how is this possible?
If you want a responsive UI - i.e., one that has a chance of being accepted in the store - then blocking on the async operation is not an option.
Instead, you have to think a bit about how you want your UI to look while the operation is in progress. And while you're thinking about that, also think about how you would want your UI to respond if the operation errors out.
Then you can code up a solution. It's possible to do this with async void, if you catch all exceptions and handle them cleanly:
public async void LoadData()
{
try
{
... // Set up "loading" UI state.
var balance = await GetBalanceAsync();
... // Set up "normal" UI state.
Balance = balance;
}
catch
{
... // Set up "error" UI state.
}
}
However, I prefer to use a type I created called NotifyTaskCompletion, which is a data-bindable wrapper for Task<T> (described in my MSDN article). Using NotifyTaskCompletion, the LoadData becomes much simpler:
public void LoadData()
{
GetBalanceOperation = new NotifyTaskCompletion<Balance>(GetBalanceAsync());
}
public NotifyTaskCompletion<Balance> GetBalanceOperation // Raises INotifyPropertyChanged when set
Then your UI can data-bind to properties on NotifyTaskCompletion<T>, such as IsNotCompleted (for the "loading" state), IsSuccessfullyCompleted and Result (for the "normal" state), and IsFaulted and ErrorMessage (for the "error" state).
There is no difference to use async await in Windows Phone 8 dev:
public class MainModel
{
public async void LoadData()
{
var data = await Foo.GetBalance();
}
}
Depends on whether you want LoadData to be synchronous (not returning until all the data has been streamed in over HTTP, and locking up the UI until then), or to begin the process and return immediately. If you can't change LoadData to async, then those are your only two options.
If you want LoadData to be synchronous:
public void LoadData() {
var task = GetBalance();
var result = task.Result; // will lock up the UI until the HTTP request returns
// now do something with result
}
If you want it to start a background process and return immediately, but for some reason don't want to mark LoadData as async:
public void LoadData() {
BeginLoadData();
}
private async void BeginLoadData() {
var result = await GetBalance();
// now do something with result
}
Though really, there's no reason not to go ahead and make LoadData async. async void does not force you to change the callers in any way (unlike Async<Task<T>>), and it's assignment-compatible with plain old non-async delegates:
public async void LoadData() {
var result = await GetBalance();
// now do something with result
}
// ...
LoadData(); // works just fine
Action myAction = LoadData; // works just fine
As you are working on asynchronus operations you need to wait until the operation is completed.The return type async/await method is always Task(TResult), to access the result of the async/await you need to use Result Property.The get accessor of Result property ensures that the asynchronous operation is complete before returning.
public void LoadData()
{
var data = GetBalance().Result;
}

Use events to forward exceptions for producer/consumer using Dataflow

I’m trying to implement a producer/consumer queue using Dataflow for HTTP requests towards a web service. I found an excellent post from Stephen Cleary, which is covering exactly this scenario. However, in contrast to Stephen’s post, I cannot mark the producer queue as complete since clients shall be able to enqueue requests throughout the entire lifetime of the application. The idea behind this approach that the client can constantly produce requests and the consumer is able to handle requests differently if more than 1 request is pending (which is required).
This requirement leads also to the fact that the consumption of the requests cannot be started after the production was finished, but have to be started the first request was enqueued. This also requires me to start the consumption in a non-blocking way (otherwise it would lead to a deadlock). I’ve done this via an async-call which is not awaited, which unfortunately hampers the exception handling. Exceptions occurring during the consumption (implementing the HTTP requests) cannot bubble up since the call of the consume-function is not awaited. I’ve introduced and event to deal with this kind of problem, but this leads me to the following questions:
Is it a good idea to use an event to forward exceptions from the consumer to the client of the producer?
Is this a good idea to implement the producer/consumer pattern in that fashion for my use case?
Are there potentially other approaches, which are more beneficial under the given circumstances?
To make it a more explicit, I’ve prepared a code example illustrating the problem I described above:
public class HttpConnector
{
private BufferBlock<RequestPayload> queue;
public delegate void ConnectorExceptionHandler(object sender, Exception e);
public event ConnectorExceptionHandler ConnectorExceptionOccured;
public Task<bool> ProduceRequest(RequestPayload payload)
{
if(this.queue == null)
{
this.queue = new BufferBlock<RequestPayload>();
this.ConsumeRequestsAsync(queue); //this call cannot be awaited since it would lead to a deadlock
//however, by not awaiting this call all exceptions raised in
//ConsumeRequestsAsync will be lost
}
return await queue.SendAsync(payload)
}
public Task ConsumeRequestsAsync(BufferBlock<RequestPayload> queue)
{
while(await queue.OutputAvailableAsync())
{
try
{
var payload = await queue.ReceiveAsync();
//do the HTTP request...
}
catch (Exception e)
{
ConnectorExceptionOccured(this, e); //fire event to forward the exception to the client
}
}
}
}
public class Client
{
private HttpConnector connector = new HttpConnector();
public Task<bool> UpdateDataAsync()
{
connector += (object sender, Exception e ) //register an event handler to receive exceptions occur
//during the consumption of the requests
{
//handle exception or re-throw
};
connector.ProduceRequest(new RequestPayload()); //produce a request
}
}
Forwarding exceptions via an event has some severe drawbacks:
Natural exception handling is not possible. If developers are aware of this mechanism, they won't catch any exception.
You cannot use AppDomain#UnhandledException for unhandled exceptions during the application runtime. In fact, if you don't have a subscription to the 'Exception'-event, the exception is completely lost.
If you have only one event to subscribe to, your exception object needs a lot of context information in order to figure out which operation caused the exception.
For our problem it turned out that it is better to use TaskCompletionSource, which is a standard technique to synchronize different threads. An instance of TaskCompletionSource class is provided by each RequestPayload object. After the consumption the TaskCompletionSource.Task is completed (either with the result or with an exception). The producer doesn't return the Task for queue.SendAsync(payload) but payload.CompletionSource.Task:
public class RequestPayload
{
public IModelBase Payload { get; set; }
public TaskCompletionSource<IResultBase> CompletionSource { get; private set; }
}
public class HttpConnector
{
private BufferBlock<RequestPayload> queue;
public Task ProduceRequest(RequestPayload payload)
{
if(this.queue == null)
{
this.queue = new BufferBlock<RequestPayload>();
this.ConsumeRequestsAsync(queue);
}
await queue.SendAsync(payload);
return await payload.CompletionSource.Task;
}
public Task ConsumeRequestsAsync(BufferBlock<RequestPayload> queue)
{
while(await queue.OutputAvailableAsync())
{
try
{
var payload = await queue.ReceiveAsync();
//do the HTTP request...
payload.CompletionSource.TrySetResult(null);
}
catch (Exception e)
{
payload.CompletionSource.TrySetException(e)
}
}
}
}
public class Client
{
private HttpConnector connector = new HttpConnector();
public Task UpdateDataAsync()
{
try
{
await connector.ProduceRequest(new RequestPayload());
}
catch(Exception e) { /*handle exception*/ }
}
}

Categories