1

my C# mainwindow starts a taskfactory Task when a button is clicked. That Task should gather data from a Serial device, but not only once. It should collect the data in "realtime". The Serial module sends a request to that Serial device. when the device answeres, it should gave the data back to the mainwindow ( I tried it with a event) and starts collecting data again: Start Task:

private  void menuStartLog_Click(object sender, RoutedEventArgs e)
{
    Librarys.SerialCom Comport = new Librarys.SerialCom();

    Task<string> serialThread = Task<string>.Factory.StartNew(() => Comport.ADVInfo(), TaskCreationOptions.LongRunning);
    textBoxMain.Text = serialThread.Result;
}

This method is called:

public string ADVInfo()
{
    openConnection();

    if (Comport.IsOpen)
    {
        Comport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
        while (true)
        {


            Console.WriteLine("Serial Task started.");
            byte[] SerialRequest = new byte[3] { 0xF0, 0x02, 0x0D };
            Comport.Write(SerialRequest.ToString());

            Console.WriteLine("Serial Thread completed.");


            //Here the task should return data to the mainwindow and request new data
        }     
    }
    return ("No open Comport!!!");
}

private static void DataReceivedHandler(
                    object sender,
                    SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    Console.WriteLine("Data Received:");
    Console.Write(indata);
}

But the thread for Serial communication is blocking the main thread. Can i return data with out waiting in the Main thread, e.g. with a event?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Basti An
  • 347
  • 1
  • 6
  • 23

1 Answers1

1

Instead of blocking with .Result, you should await the Task created by StartNew. That way, control is yielded back to the message loop while the operation executes:

private async void menuStartLog_Click(object sender, RoutedEventArgs e)
{
    Librarys.SerialCom Comport = new Librarys.SerialCom();
    Task<string> serialThread = Task<string>.Factory.StartNew(() => Comport.ADVInfo(), TaskCreationOptions.LongRunning);

    textBoxMain.Text = await serialThread;
}

If you want to generate multiple strings from the ComPort, you can return an IEnumerable<string> using yield return.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • `ADVInfo` itself should be made asynchronous using a TaskCompletionSource, eg as shown [here](http://stackoverflow.com/questions/23230375/sample-serial-port-comms-code-using-async-api-in-net-4-5?lq=1) – Panagiotis Kanavos Sep 02 '15 at 13:37