1

Background

Most of the applications that I write are hour long sequential tests for electronic equipment. The equipment under test has a specification that is a state-machine that looks like...

  1. Get the equipment into mode A.
  2. Now that the equipment is in mode A, do a test.
  3. Get the equipment into mode B.
  4. Now that the equipment is in mode B, do another different test.
  5. Get the equipment into mode C.
  6. Now that the equipment is in mode C, do a third and final test.

Note, that the equipment can only be put into mode B after going through steps 1 & 2. Then, the equipment can only be put into mode C after going through steps 3 & 4, so on and so forth. So therefore these steps have to be run in the exact order, or the equipment won't respond. Because of this model, most of my applications will consist of the following:

  1. A field, where the results of the test steps are displayed as they happen.
  2. START button (get the task running, performing the test).
  3. STOP button (launch some cancellation token to the task).
  4. PAUSE button (pauses the task, with ManualResetEvent).

The applications will typically perform in the following way:

  1. The user clicks on START and a Task will get started that runs all the steps of the test.
  2. As the steps of the test get completed, events will be launched that are consumed by the GUI.
  3. The GUI consumes the events launched by the Testing thread, and displays the results of the tests (contained in the event arguments).

Note, the only reason we even use one Task to begin with is to keep the Windows form responsive.

I am trying to adopt my coding style as much as possible to keep up with the trending patterns. I am thinking about using some of Microsoft's newer features such as async/await in order to accomplish my same old method of writing programs (shown above).

Question

Does the state-machine-esque style of the software warrant a good use-case for async/await? Will I be able to adopt this event-driven procedural style into using async/await?

  • The primary use case for async await is to keep UI responsive. The technical use case for async await is to make synchronous methods asynchronous so that you can get some other work done (on the same thread) while you're waiting for the method's result. – Robert Harvey Jul 29 '16 at 18:22
0

I'd leave well enough alone. There is a time and place for sequential code and it sounds like you have a textbook example.

Async/await are useful tools, but not the right tools for the problem you're solving.

Put this another way, which code would be easier to maintain - your current code or code restructured to use async/await?

  • I don't know how to answer that question. I've looked at alot of the examples for async/await, and it seems all of them have one thing in common... "I need to do X many things at once". For me, that's just not the case. But my question is more along the lines of... Can I use an event-driven scheme with the async/await? – Snoop Apr 11 '16 at 19:21
  • You certainly can use an event driven scheme, but why bother? I suspect your code would be more difficult to maintain. – Dan Pichelman Apr 11 '16 at 19:30
  • It sounds like you have a bit of background in this area. Unrelated to the exact question, I would just like to ask you what you think of my overall implementation. I would really like to know. I do not think there are a lot of people doing this kind of work. – Snoop Apr 11 '16 at 19:40
1

Async/await is just syntactic sugar for using Tasks. In fact, async/await makes the code able to be more procedural rather than get caught in the callback pit. For instance, one (not great) way to run a task after another task would be:

var task = StartSomething();
var continuation = task.ContinueWith(t => {
    var task2 = StartSomethingElse(t.Result);
    var continueSomethingElse = task2.ContinueWith(t2 => {
        var result2 = r2.result;
        ... // and so forth
    });
});

Which could be simplified with awaits like so:

// not precisely the same as above due to scoping, but...
var result1 = await StartSomething();
var result2 = await StartSomethingElse(result1);

But in order for async/await to save you anything, your individual steps would need to be asynchronous. If you only have one overall Task (as it sounds), async/await is not likely to save you anything.

To answer the other dimension of your question, async/await may or may not be suitable for an event-driven styles depending on the rest of your app. The general rule is if you use async/await, you should use it from top to bottom. Calling .Wait() or .Result on the task from an async method can result in a deadlock.


The logic described in the question does not sound like a state machine so much as a cancel-able background worker. A state machine usually defines all states and operations, and which operations are valid at which state, and the result state of any valid operation on a state.

It sounds like a background worker is appropriate for your stated use case.

  • This is a state-machine. I cannot get to state C, without going through A and B first. – Snoop Apr 11 '16 at 20:22
  • The equipment may very well be a state machine, but I would hesitate to label the code as such. It really has only one sequence of instructions with possibility of early exit. See Stateless for example. – Kasey Speakman Apr 11 '16 at 20:25
  • I don't see why you would hesitate. The code just tests the equipment, following along exactly through the states. – Snoop Apr 11 '16 at 20:27
0

Let's imagine that after doing each test, you had to analyze some data you recorded, and write those results out, and lets say that analysis is a somewhat computationally expensive operation and can't start until all the data is collected, while the configuration of the hardware and recording the data is cheap but it a lot of waiting.

It could then make sense to use async and await style programming for a situation like that.

While the software is getting the equipment ready for test B, and you could begin processing A's data on another thread. You would have an async method to do that, that provides your computed results. Occasionally, the setup of test B might need some results from the analysis, and there it would await those results. If the results are already done, the await is nearly instant, and if not, it will block, keeping your test procedure in order.

Rather than use async/await, you could write your own threading code and own synchronization routines to keep everything running smoothly, however that can be surprisingly challenging to get right.

The C# developers designed async/await to reflect the more common multithreading scenarios so you don't have to worry about that stuff. The await keyword basically signals the moment you need some important results from the background operation, and the compiler can figure out what can be running at any given time.

  • Problem is, there's not "the moment" where I need results. It's... Like every 5 seconds. – Snoop Apr 11 '16 at 20:18
  • @StevieV: it's a hypothetical scenario. Async/await isn't applicable to everything, don't use it where it's not appropriate. We don't know the exact details of your system, we can only give broad concepts so you can understand where async/await would be appropriate. – whatsisname Apr 11 '16 at 21:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.