C# How to make synchronous method waiting for events to fire? - c#

I have custom browser class which is capable of firing a lot of events depending on browsed page state. Now I need to perform some operations on this web page using my browser, but they have to run sequentialy, each operation needs data from the previous one.
The cleanest way to achieve this is to make a synchronous methods waiting for browser to do its job. I made it like this:
public incomplete class MyClass {
// (...) lots of stuff comes here, it's a web browser :)
public bool MySyncMethod(object data) {
bool success = false;
bool wait = true;
MyEventHandler = new EventHandler((o, e) => {
data = MyEventProvidedData; // belive me, it's threre when it fired
success = true; // let's assume it always succeed
wait = false; // now we can move on to the rest of our long chain
});
// (...) here I have some more event handlers which can end my method...
MyAsyncMethod(data); // so it started and will fire MyEventHandler soon
while (wait) System.Threading.Thread.Sleep(100);
return success;
}
}
But something seems wrong here. If I used threads, I'd just place myThread.Join() instead of my while loop and it would wait for my thread to complete. Is it something similar to Thread.Join() which can be used with events fired by controls? Is there something to use instead of while loop? Is it a cleaner way to achieve my goal? The code above works in the real app, but I think it's not optimal.
And there is a good reason I don't use threads here - all communication between threads and ActiveX control must be thread-safe, and this is not trivial to achieve. Yes, I tried :) This code was a hell to debug, so I decided to rewrite it.

Try use ManualResetEvent:
var wait = new ManualResetEvent(false);
var handler = new EventHandler((o, e) => wait.Set());
MyAsyncMethod(data, handler); // so it started and will fire handler soon
wait.WaitOne();

If it's possible to use tasks, you could use the WaitAll Method
But you say you can't use threads. Still the asyncmethod must start some kind of threading so there must be some threading involved?
If the problem is that the asyncmethod must post back to the original thread for the active x control to work, you can use the ASyncOperationManager ( shameless own blog post link: http://blog.subrosoftware.nl/?p=42 ), or the MSDN link Could that perhaps solve the thread callback issue?

Related

How to read data from stream asychronously in background

I would like to read data from a stream (serial, tcp, whatever) asynchronously and trigger events to notify other components.
Following is pseudo code, assuming "stream" is a valid stream.
public class Reader {
private _stream;
private _buffer = new bytes[4096];
public event Action<byte[], int> DataRecieved;
public async void StartReading() {
while (true) {
var nbytes = await _stream.ReadAsync(_buffer, 0, _buffer.Length);
if (nbytes == 0)
return;
var handlers = DataRecieved;
if (handlers != null)
DataRecieved(_buffer, nbytes);
}
}
}
And the caller part:
var r = new Reader();
r.OnDataRecieved += myHandler;
r.StartReading();
I'm not sure doing something like this is a good idea. I read that using asynchonous void functions is not a good idea, but here I don't want caller to wait for the result, I want to notify it when some data is available.
What's the good way to do something like that ?
void async is only considered to be used for GUI event handlers. In WinForms, events have all delegate-types of type void. Usually, you want, when using async , notify your caller when you have finished - in an asynchronous way. The .NET message-loop is considered the exception here, since you have no different possibility to use async.
In your case, the async/await keywords won't make much sense. I'd recommend to invoke your method using a Task or the ThreadPool (or BackgroundWorker).
You do not have a long running task on which you want to react in a asynchronous manner, but a parallel background-task, which should be used as such.
The idea of async/await is that the caller of a method continues after the method invocation and may execute code inside the method behind an await later. But that requires you to use await in the calling-method, which would block your main-thread.
Long story short: You have no other chance as using a second thread and use thread-synchronization.
Invoke is nothing else as placing a delegate in a queue which the message-loop reads and executes. In your case, you could do something similar: Take the read data, like the byte[] and put that in a queue (via the event). And whenever your main-thread desires to do some work, he grabs an item from the queue.
That is one option. The best solution for this issue depends strongly on your application, and as far as you didn't tell us more details about the design, I can't recommend the best way. But async/await won't be it. Definitely.
Make the method return Task to avoid async void. You can ignore that task if you want but eventually you probably want to wait for it to complete.
Also handle errors. Right now they are thrown away and the reading stops silently. You will never find bugs this way.
Wrap everything in Task.Run to make sure that this async method really runs completely asynchronously. Right now if each await completes right away this method will never return or not return in a long time. Don't risk that. Alternatively you can place await Task.Yield(); at the first line of the method.

What is the reason for "while(true) { Thread.Sleep }"?

I sometimes encounter code in the following form:
while (true) {
//do something
Thread.Sleep(1000);
}
I was wondering if this is considered good or bad practice and if there are any alternatives.
Usually I "find" such code in the main-function of services.
I recently saw code in the "Run" function in a windows azure worker role which had the following form:
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
I assume there are better ways to prevent a service (or azure worker role) from exiting.
Does anyone have a suggestion for me?
Well when you do that with Thread.Sleep(1000), your processor wastes a tiny amount of time to wake up and do nothing.
You could do something similar with CancelationTokenSource.
When you call WaitOne(), it will wait until it receives a signal.
CancellationTokenSource cancelSource = new CancellationTokenSource();
public override void Run()
{
//do stuff
cancelSource.Token.WaitHandle.WaitOne();
}
public override void OnStop()
{
cancelSource.Cancel();
}
This will keep the Run() method from exiting without wasting your CPU time on busy waiting.
An alternative approach may be using an AutoResetEvent and instantiate it signaled by default.
public class Program
{
public static readonly AutoResetEvent ResetEvent = new AutoResetEvent(true);
public static void Main(string[] args)
{
Task.Factory.StartNew
(
() =>
{
// Imagine sleep is a long task which ends in 10 seconds
Thread.Sleep(10000);
// We release the whole AutoResetEvent
ResetEvent.Set();
}
);
// Once other thread sets the AutoResetEvent, the program ends
ResetEvent.WaitOne();
}
}
Is the so-called while(true) a bad practice?
Well, in fact, a literal true as while loop condition may be considered a bad practice, since it's an unbrekeable loop: I would always use a variable condition which may result in true or false.
When I would use a while loop or something like the AutoResetEvent approach?
When to use while loop...
...when you need to execute code while waiting the program to end.
When to use AutoResetEvent approach...
...when you just need to hold the main thread in order to prevent the program to end, but such main thread just needs to wait until some other thread requests a program exit.
If you see code like this...
while (true)
{
//do something
Thread.Sleep(1000);
}
It's most likely using Sleep() as a means of waiting for some event to occur — something like user input/interaction, a change in the file system (such as a file being created or modified in a folder, network or device event, etc. That would suggest using more appropriate tools:
If the code is waiting for a change in the file system, use a FileSystemWatcher.
If the code is waiting for a thread or process to complete, or a network event to occur, use the appropriate synchronization primitive and WaitOne(), WaitAny() or WaitAll() as appropriate. If you use an overload with a timeout in a loop, it gives you cancelability as well.
But without knowing the actual context, it's rather hard to say categorically that it's either good, bad or indifferent. If you've got a daemon running that has to poll on a regular basis (say an NTP client), a loop like that would make perfect sense (though the daemon would need some logic to monitor for shutdown events occuring.) And even with something like that, you could replace it with a scheduled task: a different, but not necessarily better, design.
If you use while(true) you have no programmatic means of ending the loop from outside the loop.
I'd prefer, at least, a while(mySingletonValue) which would allow us to switch the loop as needed.
An additional approach would be to remove the functional behavior from the looping behavior. Your loop my still be infinite but it calls a function defined elsewhere. Therefore the looping behavior is completely isolated to what is being executed by the loop:
while(GetMySingletonValue())
{
someFunction();
}
In this way your singleton controls the looping behavior entirely.
There are better ways to keep the Azure Service and exit when needed.
Refer:
http://magnusmartensson.com/howto-wait-in-a-workerrole-using-system-timers-timer-and-system-threading-eventwaithandle-over-system-threading-thread-sleep
http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely/
It really depends on that //do something on how it determines when to break out of the loop.
In general terms, more appropriate way to do it is to use some synchronization primitive (like ManualResetEvent) to wait on, and the code that processes and triggers the break of the loop (on the other thread) to signal on that primitive. This way you don't have thread wasting resources by being scheduled in every second to do nothing, and is a much cleaner way to do it.
I personally don't like Thread.Sleep code. Because it locks the main thread. You can write something like this, if it is a windows application besides it allows you more flexibility and you can call it async:
bool switchControl = true;
while (switchControl) {
//do something
await Wait(1);
}
async void Wait(int Seconds)
{
DateTime Tthen = DateTime.Now;
do
{
Application.DoEvents(); //Or something else or leave empty;
} while (Tthen.AddSeconds(Seconds) > DateTime.Now);
}

Why does async method-callers behave strangely?

I'm working on a Windows 8.1 store app in which the user can save text to a file.
I've been trying to understand how to best use async and await.
This is what I've come up with:
private async void userText_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
if (addUserImput)
{
userStringlist.Add(userBox.Text);
userBox.Text = "";
addUserImput = false;
}
await WriteToFileAsync();
addUserImput = true;
}
}
And the async-method looks like this:
private async Task WriteToFileAsync()
{
string name = "userStrings.txt";
var option = CreationCollisionOption.ReplaceExisting;
var folder = Windows.Storage.ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(name, option);
await Windows.Storage.FileIO.WriteLinesAsync(file, userStringlist);
}
As soon as WriteToFileAsync reaches the await-keyword the execution will start over. In order to prevent duplicates in my list I had to add the if-statement.
It just strikes me as odd. I'm still new to this, so I might've missed something. Why does the keydown event resume from the top, doing work that has already been done?
My "workaround" works, I just don't get the logic behind the event's behaviour.
Yes, that's how asynchronous solutions work. When you hit your first actually asynchronous operation (in this case, CreateFileAsync) the method returns to its caller, which returns to its caller, and it eventually works it's way out of the entire method and back up to your application's message loop. It then continues on processing other UI messages. Some of those messages may be key down events (and they could end up being run before your asynchronous operation is completed). Other events could be things like paint events or mouse click events that lets your form do whatever it needs to interact with the user. This is what prevents it from freezing.
What you want to do is to prevent the given section of code that you have from being run concurrently. If this weren't asynchronous this is something that you would generally solve using the lock keyword, but that isn't an option for an asynchronous method. What you need is some method of preventing access to the code until any other executions of that code block finish. Fortunately there are tools available to do this. You could use a boolean, as you are, but this is somewhat fragile and fairly easy to make a mistake with as the complexity of the application grows. A Semaphore is specifically designed for this task:
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
private async void Bar()
{
try
{
await semaphore.WaitAsync();
//do stuff
}
finally
{
semaphore.Release();
}
}
The SemaphoreSlim class has a WaitAsync method specifically designed for use in asynchronous methods, such as yours. You can wait until the semaphore is free, do your code, and then ensure that you release the semaphore when done so that other code can then move into the code block.
You may need to use handled = true in this case . check if http://msdn.microsoft.com/en-us/library/system.windows.forms.keyeventargs.handled(v=vs.110).aspx works

WPF Method to wait for DocumentCompleted Event

I know this has been asked before, but I don't think these solutions are flexible. The DocumentCompleted event should be used to determine when the load has completed, not as a method for performing work. If you need to perform several different tasks that each have to navigate several times, placing the logic in the DocumentCompleted event turns it into a messy switch/case router that is hard to read and maintain.
You need something that can actually wait during your method performing navigation so you can continue your task in the method you are already in. My first though is an actual Wait() method.
I would think something like this is close:
void WaitForLoad()
{
isLoading = true;
while (isLoading)
{
if (Application.Current == null) break;
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, (DispatcherOperationCallback)delegate(object unused) { return null; }, null);
}
}
And set Isloading to false in the DocumentCompleted event.
You should be able to just call this method after whatever action will cause a pageload. It works, it has some issues.
1) it sends the CPU usage for the app up to 35% until the page has loaded, even if nothing else is happening.
2) if the application tries to close while its running, the loop will keep running and leave the app open with no windows, hence the need for the break when the app is null.
Can this be fixed, or am I coming at this all the wrong way?
Edit: I tried implementing the ManualResetEvent solution below, but it led to several other issues that I am not sure can be resolved without creating a messier situation than the one above. Since the WebBrowser is on the UI, locking the thread stop the entire app. If the work is done on the background thread it can be locked, but then accessing the WebBrowser becomes very difficult.
In your situation, it sounds like you want a specific thread to block while waiting for the document to load. In that case, you would do something like this:
protected ManualResetEvent _resetEvent = new ManualResetEvent(false);
public void WaitingThread()
{
_resetEvent.WaitOne();
// Do stuff after the web browser completes.
}
public void LoadWebPage()
{
webBrowser.Navigate(new Uri(url));
webBrowser.DocumentCompleted = (s, e) => { _resetEvent.Set(); };
}
Basically, when the document completes, you signal the event and any threads waiting on the event unblock and continue executing.
I noticed that you use Dispatcher.CurrentDispatcher.Invoke this is good for calling your method that somehow updates UI from another thread. But from code provided, I don't see any code in other thread then UI. So
Run that code on another thread.
On the close event of your application you can make isLoading=false; And more, if the method invoked is kind of long running stuff insert
if(!isLoading)
return;
//or in some other app suitable way break an execution
EDIT:
Even better way to handle this in multithreading, then just simply relay on boolean variable, is using some Synchonization object

What's a good non-networked example of the new C# Async feature?

Microsoft just announced the new C# Async feature. Every example I've seen so far is about asynchronously downloading something from HTTP. Surely there are other important async things?
Suppose I'm not writing a new RSS client or Twitter app. What's interesting about C# Async for me?
Edit I had an Aha! moment while watching Anders' PDC session. In the past I have worked on programs that used "watcher" threads. These threads sit waiting for something to happen, like watching for a file to change. They aren't doing work, they're just idle, and notify the main thread when something happens. These threads could be replaced with await/async code in the new model.
Ooh, this sounds interesting. I'm not playing with the CTP just yet, just reviewing the whitepaper. After seeing Anders Hejlsberg's talk about it, I think I can see how it could prove useful.
As I understand, async makes writing asynchronous calls easier to read and implement. Very much in the same way writing iterators is easier right now (as opposed to writing out the functionality by hand). This is essential blocking processes since no useful work can be done, until it is unblocked. If you were downloading a file, you cannot do anything useful until you get that file letting the thread go to waste. Consider how one would call a function which you know will block for an undetermined length and returns some result, then process it (e.g., store the results in a file). How would you write that? Here's a simple example:
static object DoSomeBlockingOperation(object args)
{
// block for 5 minutes
Thread.Sleep(5 * 60 * 1000);
return args;
}
static void ProcessTheResult(object result)
{
Console.WriteLine(result);
}
static void CalculateAndProcess(object args)
{
// let's calculate! (synchronously)
object result = DoSomeBlockingOperation(args);
// let's process!
ProcessTheResult(result);
}
Ok good, we have it implemented. But wait, the calculation takes minutes to complete. What if we wanted to have an interactive application and do other things while the calculation took place (such as rendering the UI)? This is no good, since we called the function synchronously and we have to wait for it to finish effectively freezing the application since the thread is waiting to be unblocked.
Answer, call the function expensive function asynchronously. That way we're not bound to waiting for the blocking operation to complete. But how do we do that? We'd call the function asynchronously and register a callback function to be called when unblocked so we may process the result.
static void CalculateAndProcessAsyncOld(object args)
{
// obtain a delegate to call asynchronously
Func<object, object> calculate = DoSomeBlockingOperation;
// define the callback when the call completes so we can process afterwards
AsyncCallback cb = ar =>
{
Func<object, object> calc = (Func<object, object>)ar.AsyncState;
object result = calc.EndInvoke(ar);
// let's process!
ProcessTheResult(result);
};
// let's calculate! (asynchronously)
calculate.BeginInvoke(args, cb, calculate);
}
Note: Sure we could start another thread to do this but that would mean we're spawning a thread that just sits there waiting to be unblocked, then do some useful work. That would be a waste.
Now the call is asynchronous and we don't have to worry about waiting for the calculation to finish and process, it's done asynchronously. It will finish when it can. An alternative to calling code asynchronously directly, you could use a Task:
static void CalculateAndProcessAsyncTask(object args)
{
// create a task
Task<object> task = new Task<object>(DoSomeBlockingOperation, args);
// define the callback when the call completes so we can process afterwards
task.ContinueWith(t =>
{
// let's process!
ProcessTheResult(t.Result);
});
// let's calculate! (asynchronously)
task.Start();
}
Now we called our function asynchronously. But what did it take to get it that way? First of all, we needed the delegate/task to be able to call it asynchronously, we needed a callback function to be able to process the results, then call the function. We've turned a two line function call to much more just to call something asynchronously. Not only that, the logic in the code has gotten more complex then it was or could be. Although using a task helped simplify the process, we still needed to do stuff to make it happen. We just want to run asynchronously then process the result. Why can't we just do that? Well now we can:
// need to have an asynchronous version
static async Task<object> DoSomeBlockingOperationAsync(object args)
{
//it is my understanding that async will take this method and convert it to a task automatically
return DoSomeBlockingOperation(args);
}
static async void CalculateAndProcessAsyncNew(object args)
{
// let's calculate! (asynchronously)
object result = await DoSomeBlockingOperationAsync(args);
// let's process!
ProcessTheResult(result);
}
Now this was a very simplified example with simple operations (calculate, process). Imagine if each operation couldn't conveniently be put into a separate function but instead have hundreds of lines of code. That's a lot of added complexity just to gain the benefit of asynchronous calling.
Another practical example used in the whitepaper is using it on UI apps. Modified to use the above example:
private async void doCalculation_Click(object sender, RoutedEventArgs e) {
    doCalculation.IsEnabled = false;
    await DoSomeBlockingOperationAsync(GetArgs());
    doCalculation.IsEnabled = true;
}
If you've done any UI programming (be it WinForms or WPF) and attempted to call an expensive function within a handler, you'll know this is handy. Using a background worker for this wouldn't be that much helpful since the background thread will be sitting there waiting until it can work.
Suppose you had a way to control some external device, let's say a printer. And you wanted to restart the device after a failure. Naturally it will take some time for the printer to start up and be ready for operation. You might have to account for the restart not helping and attempt to restart again. You have no choice but to wait for it. Not if you did it asynchronously.
static async void RestartPrinter()
{
Printer printer = GetPrinter();
do
{
printer.Restart();
printer = await printer.WaitUntilReadyAsync();
} while (printer.HasFailed);
}
Imagine writing the loop without async.
One last example I have. Imagine if you had to do multiple blocking operations in a function and wanted to call asynchronously. What would you prefer?
static void DoOperationsAsyncOld()
{
Task op1 = new Task(DoOperation1Async);
op1.ContinueWith(t1 =>
{
Task op2 = new Task(DoOperation2Async);
op2.ContinueWith(t2 =>
{
Task op3 = new Task(DoOperation3Async);
op3.ContinueWith(t3 =>
{
DoQuickOperation();
}
op3.Start();
}
op2.Start();
}
op1.Start();
}
static async void DoOperationsAsyncNew()
{
await DoOperation1Async();
await DoOperation2Async();
await DoOperation3Async();
DoQuickOperation();
}
Read the whitepaper, it actually has a lot of practical examples like writing parallel tasks and others.
I can't wait to start playing with this either in the CTP or when .NET 5.0 finally makes it out.
The main scenarios are any scenario that involves high latency. That is, lots of time between "ask for a result" and "obtain a result". Network requests are the most obvious example of high latency scenarios, followed closely by I/O in general, and then by lengthy computations that are CPU bound on another core.
However, there are potentially other scenarios that this technology will mesh nicely with. For example, consider scripting the logic of a FPS game. Suppose you have a button click event handler. When the player clicks the button you want to play a siren for two seconds to alert the enemies, and then open the door for ten seconds. Wouldn't it be nice to say something like:
button.Disable();
await siren.Activate();
await Delay(2000);
await siren.Deactivate();
await door.Open();
await Delay(10000);
await door.Close();
await Delay(1000);
button.Enable();
Each task gets queued up on the UI thread, so nothing blocks, and each one resumes the click handler at the right point after its job is finished.
I've found another nice use-case for this today: you can await user interaction.
For example, if one form has a button that opens another form:
Form toolWindow;
async void button_Click(object sender, EventArgs e) {
if (toolWindow != null) {
toolWindow.Focus();
} else {
toolWindow = new Form();
toolWindow.Show();
await toolWindow.OnClosed();
toolWindow = null;
}
}
Granted, this isn't really any simpler than
toolWindow.Closed += delegate { toolWindow = null; }
But I think it nicely demonstrates what await can do. And once the code in the event handler is non-trivial, await make programming much easier. Think about the user having to click a sequence of buttons:
async void ButtonSeries()
{
for (int i = 0; i < 10; i++) {
Button b = new Button();
b.Text = i.ToString();
this.Controls.Add(b);
await b.OnClick();
this.Controls.Remove(b);
}
}
Sure, you could do this with normal event handlers, but it would require you to take apart the loop and convert it into something much harder to understand.
Remember that await can be used with anything that gets completed at some point in the future. Here's the extension method Button.OnClick() to make the above work:
public static AwaitableEvent OnClick(this Button button)
{
return new AwaitableEvent(h => button.Click += h, h => button.Click -= h);
}
sealed class AwaitableEvent
{
Action<EventHandler> register, deregister;
public AwaitableEvent(Action<EventHandler> register, Action<EventHandler> deregister)
{
this.register = register;
this.deregister = deregister;
}
public EventAwaiter GetAwaiter()
{
return new EventAwaiter(this);
}
}
sealed class EventAwaiter
{
AwaitableEvent e;
public EventAwaiter(AwaitableEvent e) { this.e = e; }
Action callback;
public bool BeginAwait(Action callback)
{
this.callback = callback;
e.register(Handler);
return true;
}
public void Handler(object sender, EventArgs e)
{
callback();
}
public void EndAwait()
{
e.deregister(Handler);
}
}
Unfortunately it doesn't seem possible to add the GetAwaiter() method directly to EventHandler (allowing await button.Click;) because then the method wouldn't know how to register/deregister that event.
It's a bit of boilerplate, but the AwaitableEvent class can be re-used for all events (not just UI). And with a minor modification and adding some generics, you could allow retrieving the EventArgs:
MouseEventArgs e = await button.OnMouseDown();
I could see this being useful with some more complex UI gestures (drag'n'drop, mouse gestures, ...) - though you'd have to add support for cancelling the current gesture.
There are some samples and demos in the CTP that don't use the Net, and even some that don't do any I/O.
And it does apply to all multithreaded / parallel problem areas (that already exist).
Async and Await are a new (easier) way of structuring all parallel code, be it CPU-bound or I/O bound. The biggest improvement is in areas where before C#5 you had to use the APM (IAsyncResult) model, or the event model (BackgroundWorker, WebClient). I think that is why those examples lead the parade now.
A GUI clock is a good example; say you want to draw a clock, that updates the time shown every second. Conceptually, you want to write
while true do
sleep for 1 second
display the new time on the clock
and with await (or with F# async) to asynchronously sleep, you can write this code to run on the UI thread in a non-blocking fashion.
http://lorgonblog.wordpress.com/2010/03/27/f-async-on-the-client-side/
The async extensions are useful in some cases when you have an asynchronous operation. An asynchronous operation has a definite start and completion. When asynchronous operations complete, they may have a result or an error. (Cancellation is treated as a special kind of error).
Asynchronous operations are useful in three situations (broadly speaking):
Keeping your UI responsive. Any time you have a long-running operation (whether CPU-bound or I/O-bound), make it asynchronous.
Scaling your servers. Using asynchronous operations judiciously on the server side may help your severs to scale. e.g., asynchronous ASP.NET pages may make use of async operations. However, this is not always a win; you need to evaluate your scalability bottlenecks first.
Providing a clean asynchronous API in a library or shared code. async is excellent for reusability.
As you begin to adopt the async way of doing things, you'll find the third situation becoming more common. async code works best with other async code, so asynchronous code kind of "grows" through the codebase.
There are a couple of types of concurrency where async is not the best tool:
Parallelization. A parallel algorithm may use many cores (CPUs, GPUs, computers) to solve a problem more quickly.
Asynchronous events. Asynchronous events happen all the time, independent of your program. They often do not have a "completion." Normally, your program will subscribe to an asynchronous event stream, receive some number of updates, and then unsubscribe. Your program can treat the subscribe and unsubscribe as a "start" and "completion", but the actual event stream never really stops.
Parallel operations are best expressed using PLINQ or Parallel, since they have a lot of built-in support for partitioning, limited concurrency, etc. A parallel operation may easily be wrapped in an awaitable by running it from a ThreadPool thread (Task.Factory.StartNew).
Asynchronous events do not map well to asynchronous operations. One problem is that an asynchronous operation has a single result at its point of completion. Asynchronous events may have any number of updates. Rx is the natural language for dealing with asynchronous events.
There are some mappings from an Rx event stream to an asynchronous operation, but none of them are ideal for all situations. It's more natural to consume asynchronous operations by Rx, rather than the other way around. IMO, the best way of approaching this is to use asynchronous operations in your libraries and lower-level code as much as possible, and if you need Rx at some point, then use Rx from there on up.
Here is probably a good example of how not to use the new async feature (that's not writing a new RSS client or Twitter app), mid-method overload points in a virtual method call. To be honest, i am not sure there is any way to create more than a single overload point per method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncText
{
class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
TaskEx.Run(() => d.DoStuff()).Wait();
System.Console.Read();
}
public class Base
{
protected string SomeData { get; set; }
protected async Task DeferProcessing()
{
await TaskEx.Run(() => Thread.Sleep(1) );
return;
}
public async virtual Task DoStuff() {
Console.WriteLine("Begin Base");
Console.WriteLine(SomeData);
await DeferProcessing();
Console.WriteLine("End Base");
Console.WriteLine(SomeData);
}
}
public class Derived : Base
{
public async override Task DoStuff()
{
Console.WriteLine("Begin Derived");
SomeData = "Hello";
var x = base.DoStuff();
SomeData = "World";
Console.WriteLine("Mid 1 Derived");
await x;
Console.WriteLine("EndDerived");
}
}
}
}
Output Is:
Begin Derived
Begin Base
Hello
Mid 1 Derived
End Base
World
EndDerived
With certain inheritance hierarchies (namely using command pattern) i find myself wanting to do stuff like this occasionally.
here is an article about showing how to use the 'async' syntax in a non-networked scenario that involves UI and multiple actions.

Categories