How to transform the following callback-driven code to async/await pattern PROPERLY:
public class DeviceWrapper
{
// external device which provides real time stream of data
private InternalDevice device = new InternalDevice();
private List<int> accumulationBuffer = new List<int>();
public void StartReceiving()
{
// the following callback invocations might by synchronized by main
// UI message pump, particular window message pump
// or some other way
device.Synchronization = Synchronization.UI;
device.DataAvailable += DataAvailableHandler;
device.ReceivingStoppedOrErrorOccured += StopHandler;
device.Start();
}
private void DataAvailableHandler(object sender, DataEventArgs e)
{
// Filter data from e.Data and accumulate to accumulationBuffer field.
// If certail condition is met, signal pending task (if there is any)
//as complete return to the awaiting caller accumulationBuffer or perhaps temporary buffer created from accumulationBuffer
// in order to make it available to the caller.
// Handle also requested cancellation.
}
public Task<byte[]> GetData(CancellationToken token)
{
// create task returning data filtered and accumulated in DataAvailableHandler
}
}
// usage:
async void Test()
{
DeviceWrapper w = new DeviceWrapper();
w.StartReceiving();
while(true)
{
byte[] filteredData = await w.GetData(CancellationToken.Null);
Use(filteredData);
}
}
I have sought inspiration to solve this by reading .NET StreamReader class source, but it made me even more confused.
Thank you experts for any advice!
You're looking for TaskCompletionSource<byte[]>. This is an approximation of what it would look like:
public Task<byte[]> GetData(CancellationToken token)
{
cancellationToken.ThrowIfCancellationRequested;
var tcs = new TaskCompletionSource<byte[]>();
DataEventHandler dataHandler = null;
dataHandler = (o, e) =>
{
device.DataAvailable -= dataHandler;
tcs.SetResult(e.Data);
}
StopEventHandler stopHandler = null;
stopHandler = (os, se) =>
{
device.ReceivingStoppedOrErrorOccured -= stopHandler;
// Assuming stop handler has some sort of error property.
tcs.SetException(se.Exception);
}
device.DataAvailable += dataHandler;
device.ReceivingStoppedOrErrorOccured += stopHandler;
device.Start();
return tcs.Task;
}
If you use your async await properly your code would be much easier:
First of all:
If you want to call an async function you should be async yourself
every async function returns Task instead of void or Task<TResult> instead of TResult
There is one exception: the async event handler may return void
After you call an async function you can do other things until you need the answer. But you don't have to do other things.
Once you need the answer await for the Task, the result is the TResult.
Now implementing your example. There are several methods to solve this, but I think this typically is a producer - consumer pattern: we have an object that produces things in a tempo independant from another object that consumes them.
You can create this yourself, using semaphores to signal new data, but .NET already has something for this:
System.Threading.Tasks.DataFlow.BufferBlock.
You'll need to download a microsoft nuget package. See the remarks in MSDN description of BufferBlock.
A BufferBlock is something you send objects of type T to, while another task waits for objects of type T to arrive. Fully supports async / await.
Sender side:
The bufferblock implements ITargetBlock<T> where T is the type it sends.
You can send items of type T to any ITargetBlock
Consider making the sender a separate object with the ITargetBlock<T> as property.
Whenever it has data to distribute: Post it, or SendAsync if you want to use async / await. See later
Consumer side:
BufferBlock<T> implements als ISourceBlock<T>
The consumer gets the ISourceBlock where the sender sends his objects to, in this case the BufferBlock that the sender uses.
When started the consumer waits for data to arrive using Receive or ReceiveAsync.
Ok, lets put it all together:
public class DeviceWrapper
{
// external device which provides real time stream of data
private InternalDevice device = new InternalDevice();
// internal buffer replaced by the bufferBlock
BufferBlock<byte> bufferBlock = new BufferBlock<byte>()
public void StartReceiving() {...}
private async void DataAvailableHandler(object sender, DataEventArgs e)
{
// get the input and convert it to a byte
// post the byte to the buffer block asynchronously
byte byteToSend = ...
await this.bufferBlock.SendAsync(byteToSend);
}
public async Task<IEnumerable<byte>> GetData(CancellationToken token)
{
List<byte> receivedBytes = new List<byte>()
while (await this.BufferBlock.OutputAvailableAsync(token))
{ // a byte is available
byte b = await this.bufferBlock.ReceiveAsync(token);
receivedBytes.Add(b);
if (receivedBytes.Count > ...)
{
return receivedBytes;
}
// else: not enough bytes received yet, wait for more
}
}
}
async Task Test(CancellationToken token)
{
DeviceWrapper w = new DeviceWrapper();
w.StartReceiving();
while(NoStopRequested)
{
token.ThrowIfCancellationrequested();
var filteredData = await w.GetData(token);
Use(filteredData);
}
}
There is a lot more to tell with BufferBlocks, especially on how to stop them neatly if no data is available anymore MSDN has several examples about this.
See the chapter about DataFlow in parallel library
https://msdn.microsoft.com/en-us/library/hh228603(v=vs.110).aspx
Related
I am working on refactoring code that uses the Bootstrap protocol to update the firmware of several nodes in a machine. The current code looks something like this (pseudo-code):
public void StartUpdate()
{
Sokcet bootpSocket = new Socket():
StateObject bootpState = new StateObject(bootpSocket);
BOOTPReceive(bootpState);
SendMagicPacket();
while (!IsError && !IsUpdateComplete)
{
//wait for BOOTP/Update to finish before returning to caller
}
}
private void BOOTPReceive(object state)
{
bOOTPSocket.BeginReceive(PACKET_DATA, 0, PACKET_DATA.Length, 0, OnBOOTPReceive, state);
}
SendMagicPacket()
{
//create and send magic packet
// this will tell the node to respond with a BOOTPPacket
}
private void OnBOOTPReceive(IAsyncResult result)
{
StateObject state = (StateObject) result.AsyncState;
Socket handler = state.workSocket;
int bytesRcvd = handler.EndReceive(result);
packet = PACKET_DATA;
if(isValidBOOTP(packet))
{
SendBOOTPResponse();
}
else{
BOOTPReceive(); //keep listening for valid bootp response
}
}
private void SendBOOTPResponse()
{
UdpClient udpClient = new UdpClient();
udpClient.BeginSend(packetData, packetData.Length, BROADCAST_IP, (int)UdpPort.BOOTP_CLIENT_PORT, OnBOOTPSend, udpClient);
}
private void OnBOOTPSend(IAsyncResult result)
{
UdpClient udpClient = (UdpClient)result.AsyncState;
int bytesSent = udpClient.EndSend(result);
udpClient.Close();
}
What I want to do is convert this to async-await but still require that I don't return back to the caller right away. How would I go about doing this? Is this possible to do? And would this be the right thing to do since await-async propagates all the way to the top?
Pseudo-code of what I think this would look like:
public void StartUpdate()
{
bool result = await SendMagicPacket();
bool IsError = await BOOTPCommunication(); //Handles all of the BOOTP recieve/sends
//don't return to caller until BOOTPCommunication is completed. How do i do this?
}
You need to wait for the two tasks try the following:
public async Task StartUpdate()
{
var resultTask = SendMagicPacket();
var isErrorTask = BOOTPCommunication(); //Handles all of the BOOTP recieve/sends
await Task.WhenAll(new[]{resultTask, isErrorTask});
//don't return to caller until BOOTPCommunication is completed. How do i do this?
}
//wait for BOOTP/Update to finish before returning to caller
You don't need any async IO at all because you want to wait until all operations are done. I assume you have copied some sample code. Most sample code uses async socket APIs.
Switch everything over to synchronous socket APIs and you're done.
If you want to keep this async for some reason you can indeed switch to await and untangle this code. The pseudo-code you posted looks like a good goal. It forces the surrounding method to be async Task, though.
You can deal with that by making all callers recursively async as well. If you don't need to conserve threads you could block on that task and have a mostly synchronous call chain. At that point you lose all async benefits, though.
Radin was on the right track, but I think what you want is something like this:
You need to wait for the two tasks try the following:
public async Task StartUpdate()
{
var resultTask = SendMagicPacket();
var isErrorTask = BOOTPCommunication(); //Handles all of the BOOTP recieve/sends
Task.WhenAll(new[]{resultTask, isErrorTask}).Wait(); //Wait() will block so that the method doesn't return to the caller until both of the asynchronous tasks complete.
}
What that allows is SendMagicPacket and BOOTPCommunication to both fire simultaneously, but to wait for BOTH to complete. Using that pattern you can fire of N events simultaneously, while using Wait() to wait for all to finish so that the method itself returns synchronously.
I currently am using observables to manage messages being generated on bus which are being pushed over various streams.
All works well but as messages can come in, it's possible for the system to try and write multiple messages to the stream at once (i.e. messages coming in from multiple threads) or that messages are published quicker than they can be written to the stream... as you can image, this causes issues when writing.
Hence I'm trying to figure out how I can organize things so that when messages come in only one will be processed at a time. Any thoughts?
public class MessageStreamResource : IResourceStartup
{
private readonly IBus _bus;
private readonly ISubject<string> _sender;
public MessageStreamResource(IBus bus)
{
_bus = bus;
_senderSubject = new Subject<string>();
//`All` can publish messages at the same time as it's
//collecting data being generated from different threads
_bus.All.Subscribe(message => Observable.Start(() => ProcessMessage(message), TaskPoolScheduler.Default));
//Note the above hops off the calls context so that the
//writing to the stream wont slow down the caller.
}
public void Configure(IAppBuilder app)
{
app.Map("/stream", async context =>
{
...
await context.Response.WriteAsync("Lets party!\n");
await context.Response.Body.FlushAsync();
var unSubscribe = _sender.Subscribe(async t =>
{
//PROBLEM HERE
//I only want this callback to be executed
//one at a time...
await context.Response.WriteAsync($"{t}\n");
await context.Response.Body.FlushAsync();
});
...
await HoldOpenTask;
});
}
private void ProcessMessage(IMessage message)
{
_sender.OnNext(message.Payload);
}
}
If I understood the question correctly, this possibly can be done with SemaphoreSlim:
// ...
var semaphore = new SemaphoreSlim(initialCount: 1);
var unSubscribe = _sender.Subscribe(async t =>
{
//PROBLEM HERE
//I only want this callback to be executed
//one at a time...
await semaphore.WaitAsync();
try
{
await context.Response.WriteAsync($"{t}\n");
await context.Response.Body.FlushAsync();
}
finally
{
semaphore.Release();
}
});
SemaphoreSlim is IDisposable, make sure to dispose of it when appropriate.
Updated, from the second look, MapExtensions.Map
accepts Action<IAppBuilder>, so you're passing an async void lambda, essentially creating a bunch of fire-and-forget asynchronous operations. The Map call will return to the caller, while they may still be lingering around. This is most likely not what you want, is it?
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;
}
I'm writing a networked application.
Messages are sent over the transport as such:
Network.SendMessage (new FirstMessage() );
I can register an event handler to be called when this message type arrives, like so:
Network.RegisterMessageHandler<FirstMessage> (OnFirstMessageReceived);
And the event gets fired:
public void OnFirstMessageReceived(EventArgs<FirstMessageEventArgs> e)
{
}
I'm writing a custom authentication procedure for my networked application, which requires around five messages to complete.
Without using the Task Parallel Library, I would be forced to code the next step of each procedure in the preceding event handler, like so:
public void OnFirstMessageReceived(EventArgs<FirstMessageEventArgs> e)
{
Network.SendMessage( new SecondMessage() );
}
public void OnSecondMessageReceived(EventArgs<SecondMessageEventArgs> e)
{
Network.SendMessage( new ThirdMessage() );
}
public void OnThirdMessageReceived(EventArgs<ThirdMessageEventArgs> e)
{
Network.SendMessage( new FourthMessage() );
}
public void OnFourthMessageReceived(EventArgs<FourthMessageEventArgs> e)
{
// Authentication is complete
}
I don't like the idea of jumping around the source code to code a portion of this and a portion of that. It's hard to understand and edit.
I hear the Task Parallel Library substantially simplifies this solution.
However, many of the examples I read using the Task Parallel Library were related to starting a chain of active tasks. What I mean by 'active', is that each task could start when called explicitly, like so:
public void Drink() {}
public void Eat() {}
public void Sleep() {}
Task.Factory.StartNew( () => Drink() )
.ContinueWith( () => Eat() )
.ContinueWith( () => Sleep() );
This is opposite from my event-based async pattern, in which each event handler method is called only when the message is received.
In other words, I can't do something like this (but I want to):
Task.Factory.StartNew( () => OnFirstMessageReceived() )
.ContinueWith( () => OnSecondMessageReceived() )
.ContinueWith( () => OnThirdMessageReceived() )
.ContinueWith( () => OnFourthMessageReceived() );
I've read this article, but I don't quite understand it. It seems like what I need has to do with TaskCompletionSource. If I wanted to make a task from my event-based async pattern like the code block above, what would it look like?
You're right about TaskCompletionSource, it's the key to transforming EAP (event-based asynchronous pattern) to TPL's Task.
This is documented here: https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming#exposing-complex-eap-operations-as-tasks
Here is the simplified code:
public static class Extensions
{
public static Task<XDocument> GetRssDownloadTask(
this WebClient client, Uri rssFeedUri)
{
// task completion source is an object, which has some state.
// it gives out the task, which completes, when state turns "completed"
// or else it could be canceled or throw an exception
var tcs = new TaskCompletionSource<XDocument>();
// now we subscribe to completed event. depending on event result
// we set TaskCompletionSource state completed, canceled, or error
client.DownloadStringCompleted += (sender, e) =>
{
if(e.Cancelled)
{
tcs.SetCanceled();
}
else if(null != e.Error)
{
tcs.SetException(e.Error);
}
else
{
tcs.SetResult(XDocument.Parse(e.Result));
}
};
// now we start asyncronous operation
client.DownloadStringAsync(rssFeedUri);
// and return the underlying task immediately
return tcs.Task;
}
}
Now, all you need to do, to make a chain of those operations, is just to set your continuations (which is not very comfortable at the moment, and the C# 5 await and async will help alot with it)
So, this code could be used like this:
public static void Main()
{
var client = new WebClient();
client.GetRssDownloadTask(
new Uri("http://blogs.msdn.com/b/ericlippert/rss.aspx"))
.ContinueWith( t => {
ShowXmlInMyUI(t.Result); // show first result somewhere
// start a new task here if you want a chain sequence
});
// or start it here if you want to get some rss feeds simultaneously
// if we had await now, we would add
// async keyword to Main method defenition and then
XDocument feedEric = await client.GetRssDownloadTask(
new Uri("http://blogs.msdn.com/b/ericlippert/rss.aspx"));
XDocument feedJon = await client.GetRssDownloadTask(
new Uri("http://feeds.feedburner.com/JonSkeetCodingBlog?format=xml"));
// it's chaining - one task starts executing after
// another, but it is still asynchronous
}
Jeremy Likness has a blog entry title Coroutines for Asynchronous Sequential Workflows using Reactive Extensions (Rx) that might interest you. Here is the question he tries to answer:
The concept is straightforward: there are often times we want an asynchronous set of operations to perform sequentially. Perhaps you must load a list from a service, then load the selected item, then trigger an animation. This can be done either by chaining the completed events or nesting lambda expressions, but is there a cleaner way?
Every blog post I've read tells you how to consume an asynchronous method in C#, but for some odd reason never explain how to build your own asynchronous methods to consume. So I have this code right now that consumes my method:
private async void button1_Click(object sender, EventArgs e)
{
var now = await CountToAsync(1000);
label1.Text = now.ToString();
}
And I wrote this method that is CountToAsync:
private Task<DateTime> CountToAsync(int num = 1000)
{
return Task.Factory.StartNew(() =>
{
for (int i = 0; i < num; i++)
{
Console.WriteLine("#{0}", i);
}
}).ContinueWith(x => DateTime.Now);
}
Is this, the use of Task.Factory, the best way to write an asynchronous method, or should I write this another way?
I don't recommend StartNew unless you need that level of complexity.
If your async method is dependent on other async methods, the easiest approach is to use the async keyword:
private static async Task<DateTime> CountToAsync(int num = 10)
{
for (int i = 0; i < num; i++)
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
return DateTime.Now;
}
If your async method is doing CPU work, you should use Task.Run:
private static async Task<DateTime> CountToAsync(int num = 10)
{
await Task.Run(() => ...);
return DateTime.Now;
}
You may find my async/await intro helpful.
If you didn't want to use async/await inside your method, but still "decorate" it so as to be able to use the await keyword from outside, TaskCompletionSource.cs:
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
From here and here
To support such a paradigm with Tasks, we need a way to retain the Task façade and the ability to refer to an arbitrary asynchronous operation as a Task, but to control the lifetime of that Task according to the rules of the underlying infrastructure that’s providing the asynchrony, and to do so in a manner that doesn’t cost significantly. This is the purpose of TaskCompletionSource.
I saw it's also used in the .NET source, e.g. WebClient.cs:
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public Task<string> UploadStringTaskAsync(Uri address, string method, string data)
{
// Create the task to be returned
var tcs = new TaskCompletionSource<string>(address);
// Setup the callback event handler
UploadStringCompletedEventHandler handler = null;
handler = (sender, e) => HandleCompletion(tcs, e, (args) => args.Result, handler, (webClient, completion) => webClient.UploadStringCompleted -= completion);
this.UploadStringCompleted += handler;
// Start the async operation.
try { this.UploadStringAsync(address, method, data, tcs); }
catch
{
this.UploadStringCompleted -= handler;
throw;
}
// Return the task that represents the async operation
return tcs.Task;
}
Finally, I also found the following useful:
I get asked this question all the time. The implication is that there must be some thread somewhere that’s blocking on the I/O call to the external resource. So, asynchronous code frees up the request thread, but only at the expense of another thread elsewhere in the system, right? No, not at all.
To understand why asynchronous requests scale, I’ll trace a (simplified) example of an asynchronous I/O call. Let’s say a request needs to write to a file. The request thread calls the asynchronous write method. WriteAsync is implemented by the Base Class Library (BCL), and uses completion ports for its asynchronous I/O. So, the WriteAsync call is passed down to the OS as an asynchronous file write. The OS then communicates with the driver stack, passing along the data to write in an I/O request packet (IRP).
This is where things get interesting: If a device driver can’t handle an IRP immediately, it must handle it asynchronously. So, the driver tells the disk to start writing and returns a “pending” response to the OS. The OS passes that “pending” response to the BCL, and the BCL returns an incomplete task to the request-handling code. The request-handling code awaits the task, which returns an incomplete task from that method and so on. Finally, the request-handling code ends up returning an incomplete task to ASP.NET, and the request thread is freed to return to the thread pool.
Introduction to Async/Await on ASP.NET
If the target is to improve scalability (rather than responsiveness), it all relies on the existence of an external I/O that provides the opportunity to do that.
One very simple way to make a method asynchronous is to use Task.Yield() method. As MSDN states:
You can use await Task.Yield(); in an asynchronous method to force the
method to complete asynchronously.
Insert it at beginning of your method and it will then return immediately to the caller and complete the rest of the method on another thread.
private async Task<DateTime> CountToAsync(int num = 1000)
{
await Task.Yield();
for (int i = 0; i < num; i++)
{
Console.WriteLine("#{0}", i);
}
return DateTime.Now;
}