3

Consider the following situation:

One hardware device, two applications (1 C# application, 1 Firmware). The C# application sends frames to the firmware and the firmware executes scripts.

  • C# -> transmit frame[x]
  • FW -> receive frame[x]
  • FW -> execute script relating to frame[x]
  • FW -> before finished, a FW event is triggered forcing moving parts to stop (safety precaution).

C# requirement after such events are raised:

  • Poll FW for status, if status == stopped, send a resume fame.
  • Caveat: the C# logic therefore needs to adjust itself to being "restarted".

So this is the situation I have; but what I'm seeking advice with is how I should design a class which can handle the pausing and restarting of tasks an unlimited number of times.

While I can write convoluted methods which are hard to maintain through a chain of logical statements, I'm struggling with finding a design which is reusable and clean.

Such scenarios are true for ~50 unique tasks, so finding a solution I can apply everytime would save a lot of headache. Anytime a script is restarted or resumed, a physical user can easily cause a safety trigger stop, therefore a solution needs to be robust.

While I'm sure recursion would be a first good step, I'm worried that the stack limits has the potential to introduce errors.

Clarification:

In my bid to simplify things, I seem to have omitted too much. Apologies.

Firmware: Software running on a physical device which controls the hardware. I have no control over this code-base and it was designed independently while allowing USB communication.

Synchronization: There is very little or no synchronization between the C# application and the firmware. My C# code will send a frame of bytes which match up to a specification document for the firmware, and if the frame is valid, the firmware will reply saying it received the frame and will begin the work. After that, there is no direct synchronization. A task described by a frame typically has two attributes: the time it takes to execute (need to manually observe) and an end target status (complete with status identifiers). Currently I poll the firmware for the status until the target status is reached or until time-out.

Recursion: What I meant by that was (if not complete -> callSelfAgain())

Pause: User has done something to the device, wait here until they fix (can happen at ANY time during the time the firmware is running its jobs).

Restart: The user has amended the state, now start the job from the beginning (or where we left off [task dependent]).

  • 1
    sounds like somebody wants the cont monad. Usually I might say that as a trolling joke, but in your case it's actually dead-true. – Jimmy Hoffa Mar 28 '14 at 22:24
  • 1
    This is a question I could probably answer, but when I tried I realised there is too much missing. Frames? Scripts? Firmware? Paused & restarted? Recursion? Sorry, I just can't make it fit together. Maybe some specifics? Some code? Even pseudo-code? – david.pfx Mar 29 '14 at 5:55
  • I assume the application and firmware run in parallel and send messages between each other. Is there any synchronization between them? And I have no idea how recursion fits into this. – Euphoric Mar 29 '14 at 6:33
  • Updated the original post with clarifications. – BlackBox Mar 29 '14 at 12:11
3

I think your best bet is to design the system as a state machine. The idea is that you have objects symbolizing each discrete step of the process, including any state data that has accumulated so far, and by pointing to the subtask currently being executed you can reconstruct the execution from that point.

However, I've just remembered that there is a C# mechanism that actually works in this exact manner and also fulfills all of your requirements. Although they weren't made for this purpose, you can implement the design using iterators.

They already support pausing execution at arbitrary points, and also support restarting it any number of items as the need arises. They don't actually have to return a value, but they can, and that's a bonus.

public class Unit {
    private Unit() {

    }
}
public class StateMachine {

    public IEnumerable<Unit> Run(int input) {

        int working = input + 1;
        yield return null; //stop execution
        //restarting... we still have all the working state data!
        working *= input;
        //more work...
        yield return null; //stop work
        //restart...
        if (IsError()) {
            throw new Exception();
        }
        if (IsOverPrematurely()) {
            yield break;
        }
    }
}

(I might be misunderstanding whether or not your question requires a return value, though.)

  • This is a very interesting idea Greg, thank you. I'm not too sure how this would play out in practice right now, so let me get back to you on this one. – BlackBox Mar 29 '14 at 12:21
  • What you are describing is actually called coroutines. It is just that in C#, you can implement them using iterators. – Euphoric Mar 29 '14 at 15:10

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.