Basti An
Basti An

Reputation: 387

Return data while task is running

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?

Upvotes: 1

Views: 729

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149618

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.

Upvotes: 1

Related Questions