-1

I’m writing a program which samples data using serial ports. What I try to implement is a wait “loop” where I can wait several minutes and then fetch data from a serial port. While waiting, however, I fetch data from another serial port at a rate of 2Hz, this is done through timer_Elapsed events.

My problem is that as a new programmer in c# I do not know how to implement a good, reliable wait method. This is needed because I do not want anything to execute (apart from events) while waiting for next data sample. Things I have been looking at are;

    private async void wait(int time)
    {
        var delay = Task.Run(async () =>
        {
            Stopwatch sw = Stopwatch.StartNew();
            await Task.Delay(time);
            sw.Stop();
            return sw.ElapsedMilliseconds;
        });

        Debug.Write("Millisecs", delay.Result.ToString());
    }

Which works poorly, because it is non-blocking and somehow messes up serial communication.

    System.Threading.Thread.Sleep(120000);

Which freezes everythang

  • Creating one more thread

Which doesn't seem to do me any good, because I still need to freeze the main thread in order to run the other one, making timer_Elapsed - events hard to process properly.

Sadly, unable to write anything better I run following;

    while (ticks < 150)
    {
        Application.DoEvents();
    }

(int ticks is count of timer_Elapsed events)

which forces me to disable most UI buttons, the form itself and also makes me really nervous while only consuming about 50% of CPU capacity, according to task manager. I simply need advice on what coding approach is suitable for my type of scenario.

Thank you for your time!

EDIT:

I'm running a WinForm app using only one form as my UI. The whole code is a nightmare and I will not post it here.

After a couple of tries following code did it for me;

public async Void myMethod()
{
    await Task.Delay(2000);
    doStuff();
}

It is really a very simple one, I do not know what went wrong last time I tried this approach.

  • can you share the main parts of your programm? What for programm do you have console,Form? At the moment I think you need nothing to do. Let your programm run.... – tire0011 Jan 15 '16 at 12:25
  • What type of program? Web? WInform? Command line? You generally havea main thread anyway - I normally loop it in 1 second waits waiting for "exit the program" instructions. – TomTom Jan 15 '16 at 12:25
  • As the others have mentioned, your approach can depend upon the application type (Console, WinForm, Service, etc...) If this is an application with a user interface, that primary UI thread should never be blocked. You can write code to disable input or control interaction, but the interface itself should always be responsive. With that said, you would probably want to start a thread and register a callback that will notify the parent thread (or some other thread) that it has completed its work or is otherwise ready to allow another thread to perform another action. – gmiley Jan 15 '16 at 12:29
  • It is just the wrong approach, if you wait then you're screwed. Don't wait. The SerialPort.DataReceived event helps avoid waiting, if you want to use async/await then you can read with SerialPort.BaseStream.ReadAsync(). – Hans Passant Jan 15 '16 at 13:11
  • Thanks for the comments! Gives me things to think about! I'm running a WinFormApp with one form as my main UI. – NoobPointerException Jan 15 '16 at 13:14

1 Answers1

0

You could change your 'main thread' to also perform actions on timer events. You can then add logic to disable those timer events if a blocking task is running. Then, change your buttons so that instead of firing off their task directly, they update a global variable, or add to a queue, the required action.

Very basic example using a form timer:

    public Action NextAction;
    public bool Running;

    private void MainForm_Load(object sender, EventArgs e)
    {
        timer1.Tick += timer1_Tick;
        timer1.Interval = 5000;
        timer1.Start();
    }

    void timer1_Tick(object sender, EventArgs e)
    {
        if (!Running && NextAction != null)
        {
            Running = true;
            NextAction();
            Running = false;
        }
    }

    void button1_Click(object sender, EventArgs e)
    {
        NextAction = () => TaskMethod();
    }

    void TaskMethod()
    {
        // do something
    }
Steve Harris
  • 5,014
  • 1
  • 10
  • 25