Code:
using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private SerialPort _port;

        public Form1()
        {
            InitializeComponent();
            _port = new SerialPort("COM3",9600,Parity.None,8,StopBits.One)
            _port.DataReceived += PortDataReceived;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //clear text
            textBox1.Text = String.Empty;
        }
        
        void PortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (!(sender is SerialPort)) return;
            var port = (SerialPort) sender;
            textBox1.Invoke(new StringDelegate(DisplayString), port.ReadExisting());
        }

        void DisplayString(string value)
        {
            textBox1.Text += value;
        }
    }

    public delegate void StringDelegate(string value);
}
Edit: Die ThreadAccessViolation sollte nur bei ner WPF-Application auftreten. Bei WinForms läuft das alles in einem Thread.