0

A lot of good programmers (including a lot of good members of Stackoverflow) are against using Application.DoEvents() whatever the circumstances are. Actually it is even supported with plenty of articles in the net, like this one, this famous debate on SO, ...

Though, I'm stuck in a case, where (I) think DoEvents() is the unique exit (lack of experience). That's enough as introduction, let's see some coding.

I have a 'serialPort' component to connect with a controller through serial communication, send command and wait for its response, that's all.

string response = "";
bool respFlag;

private string sendCommand(string command)
{
  respFlag = false;  //initialize respFlag

  serialPort1.Write(command);  // send the command

  Stopwatch timer = Stopwatch.StartNew(); // start a timer
  while(true)
  {
    // break from the loop if receive a response
    if(respFlag) break;  

    // timeOut error if no response for more than 500msec
    if(timer.ElapsedMilliseconds >= 500) break;

    // here comes the UGLY part
    Application.DoEvents(); 
  }

   return response;
}

in DataReceived method of my serialPort, I read the existing response and break the loop

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  response = serialPort1.ReadExisting();

  // set the flag to true to exit the infinite loop in sendCommand
  respFlag = true; 
}

It's not exactly like this, but this is a sample code that shows how I sned-receive via serial communication, would you kindly show me where am I forcing myself into this pitfall?

10
  • What version of .NET are you running? Commented Feb 6, 2015 at 2:05
  • 1
    You'll find that goto is supported. So too is catch (Exception ex). It doesn't mean that you should use them. So don't use Application.DoEvents() - it is evil. Commented Feb 6, 2015 at 2:08
  • @Enigmativity, exactly man, I'm not debating use/don't use, I am seeking an alternative but can't find, that's why I asked here :) Commented Feb 6, 2015 at 2:11
  • @ScottChamberlain I am on 4.5 , VS2012 Commented Feb 6, 2015 at 2:12
  • 1
    @chouaib - Take a look at async/await, TPL, or Rx (Reactive Framework). Commented Feb 6, 2015 at 2:50

3 Answers 3

4

If you are using .NET 4.5 it is really easy to do with async/await and a TaskCompletionSource and async/await.

TaskCompletionSource<string> resultTcs = new TaskCompletionSource<string>();
private async Task<string> SendCommandAsync(string command)
{
    serialPort1.Write(command);  // send the command

    var timeout = Task.Delay(500);

    //Wait for either the task to finish or the timeout to happen.
    var result = await Task.WhenAny(resultTcs.Task, timeout).ConfigureAwait(false);

    //Was the first task that finished the timeout task.
    if (result == timeout)
    {
        throw new TimeoutException(); //Or whatever you want done on timeout.
    }
    else
    {
        //This await is "free" because the task is already complete. 
        //We could have done ((Task<string>)result).Result but I 
        //don't like to use .Result in async code even if I know I won't block.
        return await (Task<string>)result;
    }
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    var response = serialPort1.ReadExisting();
    tcs.SetResult(response);

    //reset the task completion source for another call.
    resultTcs = new TaskCompletionSource<string>();
}
Sign up to request clarification or add additional context in comments.

5 Comments

and this async method can be calld like string str = SendCommandAsync("*****"); ? right?
It would be called like string str = await SendCommandAsync("*****");
thanks for the guidance, I will read more about async/await, meanwhile I will try your solution and report back to you
the line return await (Task<string>)result; is giving an error Cannot convert from Task<Task> to Task<string> !! any hints?
@chouaib: are you sure you have the await with the call to Task.WhenAny()? If you'd left that out, that would explain the error you are getting.
0

You should use the async I/O methods. Asynchronously wait for Task<T> to complete with timeout is a good example.

Comments

0

I assume the answer is to run that loop in a different thread and send a message to the UI when the response is available. This assumes you cant do async IO for some reason

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.